Re: TextSpanner usability improvements
Dear all, in case there are people like me interested in having a basic syntax for inputting text spanners, I wrote three simple functions for that matter: \textSpan, \textSpanArrow and \textSpanDoubleArrow. They replace in practice following overrides with user input: \override TextSpanner.bound-details.left.text \override TextSpanner.bound-details.right.text \override TextSpanner.style \override TextSpanner.bound-details.right.arrow \override TextSpanner.bound-details.left.arrow The syntax of these three functions is: \textSpan "text" #'linestyle "text", and are used in combination with \startTextSpan and \stopTextSpan. Overrides and tweaks can still be used, preferably after and not before, so that what you change is not changed again by these functions. \version "2.20.0" textSpan = #(define-music-function (parser location leftmarkup style rightmarkup) (markup? symbol? markup?) #{ \override TextSpanner.bound-details.left.text = \markup { \upright #leftmarkup } \override TextSpanner.bound-details.right.text = \markup { \upright #rightmarkup } \override TextSpanner.bound-details.left-broken.text = ##f \override TextSpanner.bound-details.right-broken.text = ##f \override TextSpanner.style = #style \override TextSpanner.bound-details.right.arrow = ##f \override TextSpanner.bound-details.left.arrow = ##f #}) textSpanArrow = #(define-music-function (parser location leftmarkup style rightmarkup) (markup? symbol? markup?) #{ \override TextSpanner.style = #style \override TextSpanner.bound-details.right.stencil-align-dir-y = #CENTER \override TextSpanner.bound-details.left.stencil-align-dir-y = #CENTER \override TextSpanner.bound-details.right.arrow = ##t \override TextSpanner.bound-details.left.text = \markup { \upright #leftmarkup } \override TextSpanner.bound-details.right.text = \markup { \upright #rightmarkup } \override TextSpanner.bound-details.left-broken.text = ##f \override TextSpanner.bound-details.right-broken.text = ##f \override TextSpanner.dash-period = 1.0 #}) textSpanDoubleArrow = #(define-music-function (parser location leftmarkup style rightmarkup) (markup? symbol? markup?) #{ \override TextSpanner.style = #style \override TextSpanner.bound-details.right.stencil-align-dir-y = #CENTER \override TextSpanner.bound-details.left.stencil-align-dir-y = #CENTER \override TextSpanner.bound-details.right.arrow = ##t \override TextSpanner.bound-details.left.arrow = ##t \override TextSpanner.bound-details.left.text = \markup { \upright #leftmarkup } \override TextSpanner.bound-details.right.text = \markup { \upright #rightmarkup } \override TextSpanner.bound-details.left-broken.text = ##f \override TextSpanner.bound-details.right-broken.text = ##f \override TextSpanner.dash-period = 1.0 #}) %EXAMPLE \relative c' { \textSpan \markup { \bold "press." } #'trill \markup { \italic \center-align "norm." } c1\startTextSpan c1 c1\stopTextSpan \textSpanArrow "m. vib." #'dashed-line \markup { \center-align "senza vib."} \break c1\startTextSpan c1 c1\stopTextSpan \break \textSpanDoubleArrow \markup { \box "sul pont."} #'line "sul tasto" c1\startTextSpan c1 c1 c1\stopTextSpan \textSpan \markup {\italic "air"} #'zigzag " " c1\startTextSpan c4 c2.\stopTextSpan } [image: image.png] Cheers, Martín. Am So., 20. Sept. 2020 um 18:57 Uhr schrieb Thomas Morley < thomasmorle...@gmail.com>: > Am So., 20. Sept. 2020 um 17:30 Uhr schrieb Xavier Scheuer > : > > > > On Sun, 20 Sep 2020 at 13:03, Thomas Morley > wrote: > > > > > > 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. > > > > Hi, > > > > Great! Could you add this to issue 3176 (a proof of concept is not yet a > proper solution, but is anyway better than nothing, especially for a 7 > years old issue)? > > https://gitlab.com/lilypond/lilypond/-/issues/3176 > > > > Thank you! > > > > Cheers, > > Xavier > > > > -- > > Xavier Scheuer > > > > Done, with a slightly improved and commented code: > https://gitlab.com/lilypond/lilypond/-/issues/3176#note_415526421 > > Cheers, > Harm > -- www.martinrinconbotero.com
Re: TextSpanner usability improvements (was Re: Scheme predicative types)
Am So., 20. Sept. 2020 um 17:30 Uhr schrieb Xavier Scheuer : > > On Sun, 20 Sep 2020 at 13:03, Thomas Morley wrote: > > > > 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. > > Hi, > > Great! Could you add this to issue 3176 (a proof of concept is not yet a > proper solution, but is anyway better than nothing, especially for a 7 years > old issue)? > https://gitlab.com/lilypond/lilypond/-/issues/3176 > > Thank you! > > Cheers, > Xavier > > -- > Xavier Scheuer > Done, with a slightly improved and commented code: https://gitlab.com/lilypond/lilypond/-/issues/3176#note_415526421 Cheers, Harm
Re: TextSpanner usability improvements (was Re: Scheme predicative types)
On Sun, 20 Sep 2020 at 13:03, Thomas Morley wrote: > > 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. Hi, Great! Could you add this to issue 3176 (a proof of concept is not yet a proper solution, but is anyway better than nothing, especially for a 7 years old issue)? https://gitlab.com/lilypond/lilypond/-/issues/3176 Thank you! Cheers, Xavier -- Xavier Scheuer
Re: TextSpanner usability improvements (was Re: Scheme predicative types)
Hi Thomas, thank you for your interest in this very constructive discussion with Aaron! > 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!? Exactly, me neither. Forcing the default to be empty text without giving the user the chance to give input right there where the music is, is almost as undesirable as having “left text” and “right text” as defaults that you have to manually override. > 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. In principle, I would support this as well. > 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. Wow! I can’t wait to start playing with this! I’ll certainly report later, perhaps in a different thread, my observations. Thank you! Best regards, Martín. On 20. Sep 2020, 13:02 +0200, Thomas Morley , wrote: > > That
Re: TextSpanner usability improvements (was Re: Scheme predicative types)
Am So., 20. Sept. 2020 um 12:05 Uhr schrieb Martín Rincón Botero : > > 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 , 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 symbolspanner-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
Re: TextSpanner usability improvements (was Re: Scheme predicative types)
> 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 , wrote: > > existing
Re: TextSpanner usability improvements (was Re: Scheme predicative types)
On 2020-09-19 12:31 am, Martín Rincón Botero wrote: [ . . . ] I was going to comment on your reply in greater detail, but I realized it would not be terribly productive. In short, you and I simply disagree on what is satisfactory for syntax. And that is not a bad thing. 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. That said, \with is a powerful construct that need not be relegated to just context modification. Also, this Kool-Aid(tm) is really quite refreshing! Yes, the script I started writing and that you splendidly finished is a workaround, not a solution. I’m not a programmer, so the day I can actually make a pull request for issues like these might never come. It would be great if such spanners can be implemented! It is good to have the "non-programmer" perspective. Mind you, I would argue your use of LilyPond and interest in Scheme means you have already begun your journey as a programmer. (: -- Aaron Hill
Re: TextSpanner usability improvements (was Re: Scheme predicative types)
> I am uncertain what you mean by "proper" markup syntax. Sorry, I meant syntax for markup tagging. > while interesting, is invalid syntax and surely not proper. Perhaps > you simply meant something that *looks* like it could be valid LilyPond. how can a proposed syntax (for which functions have to be written yet) as example be invalid? It surely has to look like it could be valid Lilypond! > Including all of these as > parameters to a function could make the function unwieldy to use when > one only needs to specify a few values. Optional arguments help to some > degree, but they aren't perfect especially when there is ambiguity of > types. At no point is my suggestion to “all” of these parameters in a function. My suggestion is to have a basic function with “sensible” defaults. They can always be tweaked or overridden by the user as desired. That’s what \override and \tweak are for. > And users of TextSpanners should invest in creating > their own wrappers for commonly used items. No they shouldn’t. They have to if they want to have a legible code with a proper markup tagging. > b'4 a' g'2\startTextSpan \with { left-text = "rit." > to-barline = ##t } | > f'4 g'8 a' g'2 | a'1\stopTextSpan } I also was thinking of the better possibility that \startTextSpan can take arguments. The \with function is not meant for data input but for changing context properties. And if we’re starting to put text where it actually belongs in the music, certainly saying “left-text” for the \startTextSpan function is redundant. If \startTextSpan accepts text, \stopTextSpan should accept the right part of the text, so that it appears in the correct place in the music. A basic (hypothetical) c1\startTextSpan "left" c1 c1\stopTextSpan "right" would be a massive improvement in readability. If this function could stop being “misused” for tempo variations (if we had tempo spanners), then I suppose the italics by default could go away (I can’t think of other reason why they have to be italics by default!) > That approach would better preserve the semantics of the underlying > elements. Consuming a \tempo command only to produce a \markup that > *looks* like a MetronomeMark but is not one leads to issues as you found > with MIDI. The Tempo_performer cannot do what it needs to do as it does > not understand what the \markup means. That is not to mention that the > use of \tempo occurs at the wrong moment in the music. Such a proposed > MetronomeSpanner would terminate with an actual \tempo command on either > end at the correct moments. And the Tempo_performer could be improved > to understand how to interpolate tempos that are connected by spanners. Yes, the script I started writing and that you splendidly finished is a workaround, not a solution. I’m not a programmer, so the day I can actually make a pull request for issues like these might never come. It would be great if such spanners can be implemented! > I wonder if the parser's \etc could support defining new functions that > borrow the syntax from built-in ones: That would be nice as well :-). On 19. Sep 2020, 07:01 +0200, Aaron Hill , wrote: > > I am uncertain what you mean by "proper" markup syntax.
TextSpanner usability improvements (was Re: Scheme predicative types)
On 2020-09-18 2:06 pm, Martín Rincón Botero wrote: [...] There are two unsatisfactory problems for usability involved from my point of view. One is the impossibility to use proper markup syntax for text spanners. I am uncertain what you mean by "proper" markup syntax. Even though they are called "TextSpanners", the text can be any markup? value: { b'4 -\tweak bound-details.left.text \markup \box ? -\tweak bound-details.right.text \markup \circle ! -\tweak font-series #'bold -\tweak font-shape #'upright \startTextSpan a' g'2 | f'4 g'8 a' g'2 | a'1\stopTextSpan } Your proposed... \markupSpan { "sul pont." \arrow "sul tasto" } ...while interesting, is invalid syntax and surely not proper. Perhaps you simply meant something that *looks* like it could be valid LilyPond. [...] In the case of text spanners, the default has no musical use: a dashed line with no text on either side. The syntax of a text spanner has the serious omission of starting something without user input (\startTextSpan starts what? The user should have an "interface" to give an initial input. Consider a \textSpan function that has you specify the left and right text. What happens when you only need left-side text? Is it satisfactory for a user to have to say \textSpan "left" ""? Next, there are options for padding and whether the side of the spanner terminates in an arrow. What happens when you need to specify the padding on one side and the arrow-type on the other? Including all of these as parameters to a function could make the function unwieldy to use when one only needs to specify a few values. Optional arguments help to some degree, but they aren't perfect especially when there is ambiguity of types. The existing interface for TextSpanners requires that one manually \override or \tweak properties so that you only specify what you need. This may seem cumbersome when adjusting many things, but it is at least very clear what is going on. You certainly don't have to remember which argument is which. And users of TextSpanners should invest in creating their own wrappers for commonly used items. Consider something like this: startRitSpan = -\tweak bound-details.left.text "rit." -\tweak to-barline ##t \startTextSpan { b'4 a' g'2\startRitSpan | f'4 g'8 a' g'2 | a'1\stopTextSpan } The result is something that is more succinct to use within the actual music, uncluttered by \overrides and \tweaks. And being reusable assists in keeping the overall score consistent. (It is mildly annoying though to have to use \stopTextSpan, but it is probably better than polluting the namespace with a whole host of \stop*Span aliases that all do the same thing.) While the above is some defense of the existing interface, there could be ways to improve the experience. For instance, imagine this: { b'4 a' g'2\startTextSpan \with { left-text = "rit." to-barline = ##t } | f'4 g'8 a' g'2 | a'1\stopTextSpan } I do wonder if my obsession with ly:context-mod? goes too far, but I keep finding that the \with {} construct is a great alternative to variable argument lists. There is never any confusion as properties are well-named; plus, the construct is quite extensible. [...] The second issue is the mentioned 2013 issue. Lilypond lacks the possibility of using text spanners not only with a \tempo syntax (which thanks to your script is very well solved now!), something that makes the "music" in the code more legible (because there is proper markup of musical events) but also to format the whole thing as a \tempo marking in the score (tempo indications are not attached to the staff but to the system, and horizontally metronome marks are not attached to the first note of the measure but to the time signature above which they are centered, that's why I included \halign properties in the script as workaround). That would point to TextSpanners not being the right fit/tool for the job. What we perhaps need is something like a MetronomeSpanner and possibly a RehearsalSpanner--connecting MetronomeMarks and RehearsalMarks, respectively. And then we need a way to attach the spanner to \tempos or \marks in an equivalent manner as you attach TextSpanners to notes. That approach would better preserve the semantics of the underlying elements. Consuming a \tempo command only to produce a \markup that *looks* like a MetronomeMark but is not one leads to issues as you found with MIDI. The Tempo_performer cannot do what it needs to do as it does not understand what the \markup means. That is not to mention that the use of \tempo occurs at the wrong moment in the music. Such a proposed MetronomeSpanner would terminate with an actual \tempo command on either end at the correct moments. And the Tempo_performer could be improved to understand how to interpolate tempos that are conne