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 <l...@gmx.de>:
> 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 #})
>>
\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 #})
>>
_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user