lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: GrandStaff vertical distance


From: Thomas Morley
Subject: Re: GrandStaff vertical distance
Date: Wed, 17 Oct 2018 15:43:40 +0200

Hi Lukas-Fabian,

I finally found the time to look deeper into it.

Am So., 14. Okt. 2018 um 15:07 Uhr schrieb Lukas-Fabian Moser <address@hidden>:

> For me, there are the following issues with the systemStartDelimiterHierarchy 
> design:
>
> 1) There's an overlap between systemStartDelimiter and 
> systemStartDelimiterHierarchy, namely
> systemStartDelimiterHierarchy = #'(SystemStartBrace)
> is equivalent to (and in fact overrides, if there's a conflict)
> systemStartDelimiter = #'SystemStartBrace
> Might be ugly, might be convenient. Not sure.

I don't have a problem here.
>
> 2) The docs state that systemStartDelimiterHierarchy
> "... takes an alphabetical list of the number of staves produced. Before each 
> staff a system start delimiter can be given. It has to be enclosed in 
> brackets and takes as much staves as the brackets enclose. Elements in the 
> list can be omitted, but the first bracket takes always the complete number 
> of staves. The possibilities are SystemStartBar, SystemStartBracket, 
> SystemStartBrace, and SystemStartSquare."
> First, this seems to be plain wrong ("brackets" instead of "parentheses"). 
> Second, I have no idea what an "alphabetical list" is supposed to be. The 
> example given in the docs uses a,b,c,d as placeholders for the staves, but in 
> fact, any symbol (not equal to SystemStartBar etc.) may be used; they even 
> may be identical. I use this heavily in my code (but tbh I did not look at 
> the implementation of the systemStartDelimiterHierarchy interface).

This part of the docs should be fixed.
>
> 3) systemStartDelimiterHierarchy allows for heavy nesting:
>
> \new StaffGroup \with {
>   systemStartDelimiterHierarchy = #'((a (a (SystemStartBrace a) a) a))
> }
> <<
>   \new Staff a
>   \new Staff a
>   \new Staff a
>   \new Staff a
>   \new Staff a
>   \new Staff a
>   \new Staff a
>   \new Staff a
> >>
>
> While this is neat (and I think the syntax is in fact quite well suited for 
> constructions of this kind), I would assume that it is almost never used. Of 
> course it should stay being supported, but I would expect 99% of all use 
> cases comprise of <= 2 layers of nesting, most commonly one or several 
> top-level Brackets with some sub-Braces/Squares.
> The code I gave is tailored for a subset of this use-case, namely that in 
> which there is only one top-lavel Bracket/Square/Bar... comprising the whole 
> StaffGroup (and arbitrarily many first-order subgroups). If you want several 
> disjunct top-level Brackets and still use my function, you have to create 
> several StaffGroups - and hence you affect spacing. For the use cases I have 
> in mind, this is fine, but maybe I'm wrong. Of course this might be changed.
>
>
> So, basically I think we should
> - keep systemStartDelimiterHierarchy as it is

yep

> - improve the docs for this (I could try and come up with an improved 
> explanation)

Would be very nice.

> - provide a simple function (like the \setDelimiters I proposed) that allows 
> for easier setting of delimiters in the common use-case of <= 2 nesting 
> levels.
>
> What do you think?

I'd like to propose the code below. Attached as well.

It stores the info in a string, which is converted to a nested list
suitable for 'systemStartDelimiterHierarchy'. It can be nested in
arbitrary depth.

I used the following signs:
[] indicating start/end of SystemStartBracket
{} indicating start/end of SystemStartBrace
<> indicating start/end of SystemStartSquare
() indicating start/end of SystemStartBar
Other elements should be of string-length 1

I'm not that happy with the ones for SystemStartSquare and
SystemStartBar. Though I looked for signs mirroring each others and
not hard to type.
After adding the definition for 'remove-whitespace' from 2.19.xx and
'parser'/'location' as the default arguments for a music-function it
works in 2.18.2 as well.


What do you think?

Cheers,
  Harm


\version "2.18.2"

%% build in since 2.19.xx, c/p here to make it work with 2.18.2
#(define (remove-whitespace strg)
"Remove characters satisfying @code{char-whitespace?} from string @var{strg}"
  (if (guile-v2)
      (string-delete char-whitespace? strg)
      (string-delete strg char-whitespace?)))

#(define (string->raw-system-start-hierarchy-list strg)
"Takes the string @var{strg} which may contain {}[]<>().
Those are transformed according to the local 'ref-list' and are returned as
pairs where the cdr is the nesting-level.
Other elements are supposed to be of string-length 1 and are transformed to #f.
Both will build a list.
The finally returned result is a pair, containing the final list and the
greatest nesting level.
Example:
\"-[--]-\"
->
((#f (SystemStartBracket . 1) SystemStartBracket #f #f (#t . 1) #f) . 1)
"
  (let* ((cleared-strg (remove-whitespace strg))
         (ref-list
           '((#\{ . SystemStartBrace)
             (#\[ . SystemStartBracket)
             (#\( . SystemStartBar)
             (#\< . SystemStartSquare)
             (#\} . #t)
             (#\] . #t)
             (#\) . #t)
             (#\> . #t)
             ))
         (nest-lvl 0)
         (max-nest-lvl 0)
         (ready-list
           (append-map
             (lambda (x)
               ;; Look into 'ref-list'
               ;;   (a) - if a symbol is returned, return it as pair with its
               ;;         'nest-lvl'
               ;;       - increase 'nest-lvl'
               ;;       - probably increse 'max-nest-lvl' as well
               ;;   (b) - if it returns #t, return it as pair with its
               ;;         'nest-lvl'
               ;;       - decrease 'nest-lvl'
               ;;   (c) if it returns #f, return it
               ;; All are wrapped into a list to make outer append-map work
               (let* ((el (assoc-get x ref-list)))
                 (cond ((symbol? el)
                          (set! nest-lvl (1+ nest-lvl))
                          (if (> nest-lvl max-nest-lvl)
                              (set! max-nest-lvl nest-lvl))
                          ;; Urgh, adding another 'el' is a ugly hack to make
                          ;; 'split-list-by-separator' work later
                          (list (cons el nest-lvl) el))
                       (el
                         (set! nest-lvl (1- nest-lvl))
                         (list (cons el (1+ nest-lvl))))
                       (else
                         (list el)))))
            (string->list cleared-strg))))
    (cons ready-list max-nest-lvl)))

#(define (helper l nest-lvl)
"Creates a nested list relying on whether the given list 'l' contains
pairs and the there stored nesting level.
Starting with the given 'nest-lvl', which is supposed to be the
maximum nesting level for the most inner of the resulting sub-list(s).
'l' should be supplied by 'string->raw-system-start-hierarchy-list'."
  (if (zero? nest-lvl)
      l
      (let* ((splitted-ls
                (split-list-by-separator
                  l
                  (lambda (x) (and (pair? x) (eq? (cdr x) nest-lvl)))))
             (result
               (append-map
                 (lambda (el)
                   (if (and (pair? el) (symbol? (car el)))
                       (list el)
                       el))
                 splitted-ls)))
        (helper result (1- nest-lvl)))))

#(define (system-start-hierarchy-list strg)
  (let ((lst (string->raw-system-start-hierarchy-list strg)))
    (helper (car lst) (cdr lst))))

%% For conveniance
setSystemStartDelimiterHierarchy =
#(define-music-function (parser location strg) (string?)
"Derived from @var{strg} a nested list suitable for setting
@code{systemStartDelimiterHierarchy} is created and applied there.

@var{strg} may contain:
[] indicating start/end of SystemStartBracket
{} indicating start/end of SystemStartBrace
<> indicating start/end of SystemStartSquare
() indicating start/end of SystemStartBar
Other elements should be of string-length 1.
Not properly nested brackets/braces/squares/bars like [xx<x]x> will not error,
but cause strange results.
"
  #{
     \set systemStartDelimiterHierarchy = #(system-start-hierarchy-list strg)
  #})


\new Score
  \with {
      \setSystemStartDelimiterHierarchy "-[-{-<<->>-}-]-[[--]]-"
    \override SystemStartSquare.collapse-height = 1
  }
  <<
    $@(make-list 10 #{ \new Staff R1 #})
  >>


<<
  \new Staff R1
  \new StaffGroup
    \with {
      \setSystemStartDelimiterHierarchy "-{---}[<<<{[--]}>>>]--"
      %% Added for better viewing
      \override SystemStartBar.color = #red
      \offset X-offset -1 SystemStartBar
      \override SystemStartSquare.collapse-height = 1
    }
    <<
      $@(make-list 10 #{ \new Staff R1 #})
    >>
  \new Staff R1
>>

%% Not properly nested
\new Score
  \with {
    \setSystemStartDelimiterHierarchy "{[1 <2 3] [4 5> 6]"
  }
  <<
    $@(make-list 6 #{ \new Staff R1 #})
  >>

Attachment: system-start-hierarchy-string-interface-01.ly
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]