> I came across LSR #304 https://lsr.di.unimi.it/LSR/Item?id=304 and I
> think we should suggest a coding with variables there, like this:
> [...]

Yes, LilyPond should be both more supportive and more 'user friendly'
here; this is tracked as

  https://gitlab.com/lilypond/lilypond/-/issues/6525

Another related issue is support for trill pitch change accidental
marks, see

  https://gitlab.com/lilypond/lilypond/-/issues/6724

I've written some support code for `musicxml2ly` that has just been
added to master; see file `python/musicxml2ly_definitions.py`.  You
need a binary compiled from current master to get the trill pitch
change accidental mark at the right vertical position as shown in the
attached image.  Maybe the code gives you more ideas.


    Werner
\version "2.25.17"

% \accs-ornament
% --------------
%
% Position the `above` and `below` markup lists as vertical stacks
% above and below markup `script`, respectively.  `above` and `below`
% are by default horizontally centered on `script` (controlled by the
% property `acc-dir`), printed at a size given by the property
% `acc-font-size` (default value -5), and a color given by the
% property `acc-color` (default is black).  Between all markups a
% vertical space given by the property `acc-padding` (default value
% 0.2) is inserted.  The `above` stack grows from bottom to top, while
% the `below` stack grows from top to bottom.
%
% If either `above` or `below` is an empty argument, or if `script` is
% set to `#f`, the corresponding argument is not printed.
%
% If an element of `above`, `script`, or `below` is a plain string,
% check the following.
%
% * If the string consists entirely of one or more characters from the
%   accidental set '♮♭♯𝄪𝄫' (not counting a possible enclosure), add
%   `\number` internally as a prefix to use the Emmentaler font.
%
% * Otherwise the element is taken as a glyph name (again not counting
%   a possible enclosure), to be internally accessed with the
%   `\musicglyph` command.
%
% * (Not for `script`.)  If an element of `above` or `below` is a
%   plain string and the first and last character is `(` and `)`,
%   respectively, the element gets enclosed in parentheses.  The same
%   holds for `[` and `]`, enclosing the element in brackets.  The
%   font size of the enclosure characters is controlled by the
%   property `enclosure-font-size` (default value -2).
%
% Example:
%
% ```
% \markup \override #'(acc-padding . 0.5)
%         \accs-ornament { "♭" "(♯)" } "scripts.haydnturn" {}
% ```

#(define-markup-command (accs-ornament layout props
                                       above script below)
   (markup-list? markup? markup-list?)
   #:properties ((acc-font-size -5)
                 (acc-color black)
                 (acc-padding 0.3)
                 (acc-dir CENTER)
                 (enclosure-font-size -2))

   (define enclosure-regex
     ;; `(?(-3) ...)` is a 'conditional subpattern' that is only
     ;; considered for matching if the subpattern three opening
     ;; parentheses earlier (i.e., the first group) matches.
     (ly:make-regex "(?x) ^ ( [([] ) ?
                            ( [^]()[] + )
                            ( (?(-3) [])] ) ) $"))

   (define charset:accidentals (string->char-set "♮♭♯𝄪𝄫"))

   (define (musicglyph-or-number-markup arg)
     (if (string-every charset:accidentals arg)
         (make-number-markup arg)
         (make-musicglyph-markup arg)))

   (define (with-enclosure-markup arg)
     (let ((match (ly:regex-exec enclosure-regex arg)))
       (if match
           (let* (;; `left` is `#f` if there is no enclosure.
                  (left (ly:regex-match-substring match 1))
                  (left (if left
                            (make-normalsize-markup
                             (make-fontsize-markup
                              enclosure-font-size left))
                            #f))
                  (glyph (ly:regex-match-substring match 2))
                  ;; `right` is `""` if there is no enclosure.
                  (right (ly:regex-match-substring match 3))
                  (right (if (string-null? right)
                             #f
                             (make-normalsize-markup
                              (make-fontsize-markup
                               enclosure-font-size right)))))
             (make-concat-markup
              (list
               (or left "")
               (musicglyph-or-number-markup glyph)
               (or right ""))))
           #f)))

   (define (to-markup arg enclosure)
     (if (string? arg)
         (if (string-null? arg)
             #f
             (if enclosure
                 (with-enclosure-markup arg)
                 (musicglyph-or-number-markup arg)))
         arg))

   (define (make-acc-stencil arg)
     (if arg
         (interpret-markup
          layout props
          (make-halign-markup
           acc-dir
           (make-with-color-markup
            acc-color
            (make-fontsize-markup
             acc-font-size arg))))
         #f))

   (let* ((above (map (lambda (x) (to-markup x #t)) above))
          (above-stils (map (lambda (x)
                              (make-acc-stencil x))
                            above))

          (script (to-markup script #f))
          (script-stil (if script
                           (interpret-markup layout props script)
                           empty-stencil))

          (below (map (lambda (x) (to-markup x #t)) below))
          (below-stils (map (lambda (x)
                              (make-acc-stencil x))
                            below))

          (script-stil (fold (lambda (elem previous)
                               (ly:stencil-combine-at-edge
                                previous Y UP elem acc-padding))
                             script-stil
                             above-stils))
          (script-stil (fold (lambda (elem previous)
                               (ly:stencil-combine-at-edge
                                previous Y DOWN elem acc-padding))
                             script-stil
                             below-stils)))
     script-stil))


% \acc-ornament
% -------------
%
% This function behaves similar to `\accs-ornament` with the
% difference that `above` and `below` are single markups, not markup
% lists.  If one of the arguments is an empty string, it is not
% printed.
%
% Example:
%
% ```
% \markup \acc-ornament "[♭]" "scripts.turn" ♯
% ```

#(define-markup-command (acc-ornament layout props
                                      above script below)
   (markup? markup? markup?)
   #:properties (accs-ornament-markup)
   (accs-ornament-markup layout props
                         (if (and (string? above) (string-null? above))
                             '()
                             (list above))
                         (if (and (string? script) (string-null? script))
                             #f
                             script)
                         (if (and (string? below) (string-null? below))
                             '()
                             (list below))))


% Some shorthands to make the usage of `\acc-ornament` more
% comfortable for simple cases.


ornament =
#(define-music-function (above script below)
   (string? string? string?)
   #{
     \tweak parent-alignment-X #CENTER
     \tweak self-alignment-X #CENTER
     -\markup \acc-ornament #above #script #below
   #})


accTrill =
#(define-music-function (above)
   (string?)
   #{
     \tweak parent-alignment-X #CENTER
     \tweak self-alignment-X #CENTER
     -\markup
        \override #'((acc-dir . -1.3)
                     (acc-padding . -0.4))
        \acc-ornament #above "scripts.trill" ""
   #})


#(define-markup-command (trill-acc-tweak layout props above)
   (string?)
   (interpret-markup
    layout props
    #{
      \markup
        \override #'((acc-dir . -1.3)
                     (acc-padding . -0.4))
        \with-dimension-from #X
          \with-true-dimension #X \musicglyph "scripts.trill"
            \acc-ornament
              #above
              \with-true-dimension #X \musicglyph "scripts.trill"
          ""
    #}))


% `color` and `size` are optional.  If `size` is present, `color` must
% be present, too.  `size` also sets the `enclosure-font-size`
% property (three magsteps larger).
trillTweak =
#(define-music-function (acc color size music)
   (string? (color? black) (number?) ly:music?)
   (let* ((override (list `(acc-color . ,color)))
          (override (if size
                        (cons `(enclosure-font-size . ,(+ size 3))
                         (cons `(acc-font-size . ,size) override))
                        override)))
     #{
       \tweak bound-details.left.text
         \markup \override #override
                   \trill-acc-tweak #acc
       #music
     #}))

%
% Examples.
%

{
  g'1 _> ^\ornament "[♭]" "scripts.turn" "(♯)"
  \after 1*5/8 \tweak outside-staff-priority ##f
               \tweak avoid-slur #'inside
               ^\ornament "" "scripts.turn" ♯
    d''2..( e''8)
  b'1^> _\accTrill ♮
  c'1
  \mark\markup
         \override #`((acc-padding . 0.5)
                      (acc-dir . ,LEFT))
         \acc-ornament \number 1 \segno \number 2
  c'1
  \mark\markup \with-color #blue
         \override #`((acc-padding . 0.5)
                      (acc-font-size . -5)
                      (acc-color . ,green)
                      (enclosure-font-size . 0))
         \accs-ornament { "[♯]" "(♭)" }
                        \segno
                        { \with-color #red \number 3 \number 4 }
  c'1
  b'1\trillTweak "[♯]" "#FF0000" \startTrillSpan
  b'1^\ornament ♮ "" "" <>\stopTrillSpan
  a'1\trillTweak "♮" "#FF0000" #0 \startTrillSpan <>\stopTrillSpan
  g'1\trillTweak ♭ \startTrillSpan <>\stopTrillSpan
}

Reply via email to