Am So., 20. Sept. 2020 um 12:05 Uhr schrieb Martín Rincón Botero <martinrinconbot...@gmail.com>: > > In short, you and I simply > > disagree on what is satisfactory for syntax. > > > Well, it seems we already agreed on one satisfactory syntax with the way you > finished the script in the other thread, so I suppose it’s not impossible to > agree on something ;-). > > We just come to LilyPond from two different perspectives. Folks > > like me will try to make the best of the existing system, and folks like > > you will contribute to improving its syntactic elegance. > > > I hadn’t thought about it that way. I certainly give a lot of importance to > syntax. Perhaps I should try to contribute in that territory somehow. Not a > being a Scheme wizard limits my powers though. > > That said, \with is a powerful construct that need not be relegated to > > just context modification. > > > I suppose the \with construct could be extended to uses it doesn’t have right > now. But I guess one would need to understand first why isn’t that > construction so often required in the first place. > > It is good to have the "non-programmer" perspective. > > > I’m glad that’s the case. Thank you for being so helpful with non-programmers > like me! :-). > > Best regards, > Martín. > On 19. Sep 2020, 17:41 +0200, Aaron Hill <lilyp...@hillvisions.com>, wrote: > > > existing
Hi Martin, in general I'm more with Aaron. P.e., I have no clue which default text one could think of for TextSpanner's left/right-text!? Otoh, I'd wish we'd have a LilyPond-data-structure to assign a list of key/value pairs in ly-syntax to a variable. Right now we can do so at top-level, in layout, paper and \with. That said, find attached a TempoSpanner-coding. I'm not sure it's the best approach at all. For sure there's wide room for improvements. Probably the best one could say: it's a proof of concept. Cheers, Harm
\version "2.20.0" #(define-event-class 'tempo-span-event 'span-event) #(define (add-grob-definition grob-name grob-entry) (let* ((meta-entry (assoc-get 'meta grob-entry)) (class (assoc-get 'class meta-entry)) (ifaces-entry (assoc-get 'interfaces meta-entry))) (set-object-property! grob-name 'translation-type? ly:grob-properties?) (set-object-property! grob-name 'is-grob? #t) (set! ifaces-entry (append (case class ((Item) '(item-interface)) ((Spanner) '(spanner-interface)) ((Paper_column) '((item-interface paper-column-interface))) ((System) '((system-interface spanner-interface))) (else '(unknown-interface))) ifaces-entry)) (set! ifaces-entry (uniq-list (sort ifaces-entry symbol<?))) (set! ifaces-entry (cons 'grob-interface ifaces-entry)) (set! meta-entry (assoc-set! meta-entry 'name grob-name)) (set! meta-entry (assoc-set! meta-entry 'interfaces ifaces-entry)) (set! grob-entry (assoc-set! grob-entry 'meta meta-entry)) (set! all-grob-descriptions (cons (cons grob-name grob-entry) all-grob-descriptions)))) #(define tempo-text->spanner-text (lambda (grob) (let* ((bound-left (ly:spanner-bound grob LEFT)) (bound-right (ly:spanner-bound grob RIGHT)) (bound-left-ext (ly:grob-extent bound-left bound-left X)) (bound-left-center (interval-center bound-left-ext)) (bound-right-ext (ly:grob-extent bound-right bound-right X)) (bound-right-center (interval-center bound-right-ext)) (bound-details (ly:grob-property grob 'bound-details)) (details-right (assoc-get 'right bound-details)) (details-left (assoc-get 'left bound-details)) (text-padding-left (assoc-get 'text-padding details-left)) (text-padding-right (assoc-get 'text-padding details-right)) (left-bound-text (ly:grob-property bound-left 'text)) (right-bound-text (ly:grob-property bound-right 'text))) (ly:grob-set-nested-property! grob '(bound-details left text) #{ \markup { #left-bound-text \hspace #text-padding-left } #}) (ly:grob-set-nested-property! grob '(bound-details right text) #{ \markup { \hspace #text-padding-right #right-bound-text } #}) (ly:grob-set-nested-property! grob '(bound-details left padding) (- bound-left-center)) (ly:grob-set-nested-property! grob '(bound-details right padding) (+ text-padding-right bound-right-center)) (ly:side-position-interface::move-to-extremal-staff grob)))) #(add-grob-definition 'TempoSpanner `((after-line-breaking . ,tempo-text->spanner-text) (bound-details . ((left . ((Y . 0) (padding . 0.25) (text-padding . 0.4) (stencil-offset . (0 . -0.5)) )) (right . ((Y . 0) (padding . 0.25) (stencil-offset . (0 . -0.5)) (text-padding . 0.4) )) )) (dash-fraction . 0.4) (dash-period . 2.0) (direction . ,UP) (font-shape . upright) (left-bound-info . ,ly:line-spanner::calc-left-bound-info) (outside-staff-priority . 350) (padding . 0.8) (right-bound-info . ,ly:line-spanner::calc-right-bound-info) (staff-padding . 0.8) (stencil . ,ly:line-spanner::print) (style . dashed-line) (vertical-skylines . ,grob::unpure-vertical-skylines-from-stencil) (meta . ((class . Spanner) (interfaces . (font-interface line-interface line-spanner-interface outside-staff-interface side-position-interface)))))) #(define scheme-event-spanner-types '( (TempoSpanEvent . ((description . "Used to signal where scheme text spanner brackets start and stop.") (types . (tempo-span-event span-event event)) )) )) #(set! scheme-event-spanner-types (map (lambda (x) (set-object-property! (car x) 'music-description (cdr (assq 'description (cdr x)))) (let ((lst (cdr x))) (set! lst (assoc-set! lst 'name (car x))) (set! lst (assq-remove! lst 'description)) (hashq-set! music-name-to-property-table (car x) lst) (cons (car x) lst))) scheme-event-spanner-types)) #(set! music-descriptions (append scheme-event-spanner-types music-descriptions)) #(set! music-descriptions (sort music-descriptions alist<?)) #(define (axis-offset-symbol axis) (if (eqv? axis X) 'X-offset 'Y-offset)) #(define (set-axis! grob axis) (if (not (number? (ly:grob-property grob 'side-axis))) (begin (set! (ly:grob-property grob 'side-axis) axis) (ly:grob-chain-callback grob (if (eqv? axis X) ly:side-position-interface::x-aligned-side side-position-interface::y-aligned-side) (axis-offset-symbol axis))))) tempoSpannerEngraver = #(lambda (context) (let ((span '()) (finished '()) (mm-start #f) (mm-stop #f) (bound-left #f) (bound-right #f)) (make-engraver (acknowledgers ((metronome-mark-interface engraver grob source-engraver) (let* ((details (ly:grob-property grob 'details)) (start-tempo-span (assoc-get 'start-tempo-span details #f)) (stop-tempo-span (assoc-get 'stop-tempo-span details #f))) (if start-tempo-span (set! mm-start grob)) (if stop-tempo-span (set! mm-stop grob))))) ((process-music trans) (if mm-stop (if (null? span) (ly:warning "You're trying to end a scheme text spanner but you haven't started one.") (begin (set! finished span) (ly:engraver-announce-end-grob trans finished mm-stop) (set! span '()) (set! bound-right mm-stop) (set! mm-stop #f)))) (if mm-start (begin (set! span (ly:engraver-make-grob trans 'TempoSpanner '())) (set-axis! span Y) (set! bound-left mm-start) (set! mm-start #f)))) ((stop-translation-timestep trans) (if (and (ly:spanner? span) (ly:grob? bound-left)) (begin (ly:spanner-set-bound! span LEFT bound-left) (ly:grob-set-property! bound-left 'stencil '()) (set! bound-left #f))) (if (and (ly:spanner? finished) (ly:grob? bound-right)) (begin (ly:spanner-set-bound! finished RIGHT bound-right) (set! finished '()) (ly:grob-set-property! bound-right 'stencil '()) (set! bound-right #f) (set! mm-stop #f)))) ((finalize trans) (if (ly:spanner? finished) (begin (if (null? (ly:spanner-bound finished RIGHT)) (ly:spanner-set-bound! finished RIGHT (ly:context-property context 'currentMusicalColumn))) (set! finished '()))) (if (ly:spanner? span) (begin (ly:warning "I think there's a dangling scheme text spanner :-(") (ly:grob-suicide! span) (set! span '()))))))) \layout { \context { \Global \grobdescriptions #all-grob-descriptions } \context { \Score \consists \tempoSpannerEngraver } } startTempoSpan = \once \override Score.MetronomeMark.details.start-tempo-span = ##t stopTempoSpan = \once \override Score.MetronomeMark.details.stop-tempo-span = ##t %%%%%%%%%%%%%%%%%%%%%%%%% %% EXAMPLES %%%%%%%%%%%%%%%%%%%%%%%%% %#(ly:set-option 'debug-skylines #t) \paper { ragged-right = ##f } mus = { \tempo "Moderato" b1 \startTempoSpan \tempo "accellerando" b1 b \break \stopTempoSpan \tempo "Allegro" 4 = 120 c' c' c' \tempo "Adagio" d' \startTempoSpan \tempo "rit." \override Score.TempoSpanner.bound-details.right.text-padding = 0 c' \once \override Score.MetronomeMark.X-offset = 0 \stopTempoSpan \tempo \markup \translate #'(2 . 0.5) \draw-line #'(0 . -0.5) f' } \new Staff \mus << \mus \mus >>