Am So., 20. Sept. 2020 um 12:05 Uhr schrieb Martín Rincón Botero
<[email protected]>:
>
> 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 <[email protected]>, 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
>>