\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 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 #}) >>