;;;;
;;;; source file of the GNU LilyPond music typesetter
;;;;
-;;;; (c) 1998--2007 Jan Nieuwenhuizen <janneke@gnu.org>
+;;;; (c) 1998--2009 Jan Nieuwenhuizen <janneke@gnu.org>
;;;; Han-Wen Nienhuys <hanwen@xs4all.nl>
+; for take, drop, take-while, list-index, and find-tail:
+(use-modules (srfi srfi-1))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; constants.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; parser <-> output hooks.
-
+(define-public (collect-bookpart-for-book parser book-part)
+ "Toplevel book-part handler"
+ (define (add-bookpart book-part)
+ (ly:parser-define!
+ parser 'toplevel-bookparts
+ (cons book-part (ly:parser-lookup parser 'toplevel-bookparts))))
+ ;; If toplevel scores have been found before this \bookpart,
+ ;; add them first to a dedicated bookpart
+ (if (pair? (ly:parser-lookup parser 'toplevel-scores))
+ (begin
+ (add-bookpart (ly:make-book-part
+ (ly:parser-lookup parser 'toplevel-scores)))
+ (ly:parser-define! parser 'toplevel-scores (list))))
+ (add-bookpart book-part))
+
(define-public (collect-scores-for-book parser score)
(ly:parser-define!
parser 'toplevel-scores
(cons score (ly:parser-lookup parser 'toplevel-scores))))
-(define (collect-music-aux score-handler parser music)
+(define-public (collect-music-aux score-handler parser music)
(define (music-property symbol)
(let ((value (ly:music-property music symbol)))
(if (not (null? value))
(let*
((paper (ly:parser-lookup parser '$defaultpaper))
(layout (ly:parser-lookup parser '$defaultlayout))
-
(count (ly:parser-lookup parser 'output-count))
- (base (ly:parser-output-name parser)))
+ (base (ly:parser-output-name parser))
+ (output-suffix (ly:parser-lookup parser 'output-suffix)) )
+
+ (if (string? output-suffix)
+ (set! base (format "~a-~a" base (string-regexp-substitute
+ "[^a-zA-Z0-9-]" "_" output-suffix))))
;; must be careful: output-count is under user control.
(if (not (integer? count))
(if (> count 0)
(set! base (format #f "~a-~a" base count)))
-
(ly:parser-define! parser 'output-count (1+ count))
(process-procedure book paper layout base)
))
(lset-difference eq? a b))
(define-public (uniq-list lst)
- "Uniq LST, assuming that it is sorted"
+ "Uniq LST, assuming that it is sorted. Uses equal? for comparisons."
(reverse!
(fold (lambda (x acc)
(if (null? acc)
(list x)
- (if (eq? x (car acc))
+ (if (equal? x (car acc))
acc
(cons x acc))))
'() lst) '()))
-(define (split-at-predicate predicate lst)
- "Split LST = (a_1 a_2 ... a_k b_1 ... b_k)
- into L1 = (a_1 ... a_k ) and L2 =(b_1 .. b_k)
- Such that (PREDICATE a_i a_{i+1}) and not (PREDICATE a_k b_1).
- L1 is copied, L2 not.
-
- (split-at-predicate (lambda (x y) (= (- y x) 2)) '(1 3 5 9 11) (cons '() '()))"
-
- ;; " Emacs is broken
-
- (define (inner-split predicate lst acc)
- (cond
- ((null? lst) acc)
- ((null? (cdr lst))
- (set-car! acc (cons (car lst) (car acc)))
- acc)
- ((predicate (car lst) (cadr lst))
- (set-car! acc (cons (car lst) (car acc)))
- (inner-split predicate (cdr lst) acc))
- (else
- (set-car! acc (cons (car lst) (car acc)))
- (set-cdr! acc (cdr lst))
- acc)))
-
- (let* ((c (cons '() '())))
- (inner-split predicate lst c)
- (set-car! c (reverse! (car c)))
- c))
-
-(define-public (split-list-by-separator lst sep?)
- "(display (split-list-by-separator '(a b c / d e f / g) (lambda (x) (equal? x '/))))
- =>
- ((a b c) (d e f) (g))
- "
- ;; " Emacs is broken
- (define (split-one sep? lst acc)
- "Split off the first parts before separator and return both parts."
- (if (null? lst)
- (cons acc '())
- (if (sep? (car lst))
- (cons acc (cdr lst))
- (split-one sep? (cdr lst) (cons (car lst) acc)))))
-
- (if (null? lst)
- '()
- (let* ((c (split-one sep? lst '())))
- (cons (reverse! (car c) '()) (split-list-by-separator (cdr c) sep?)))))
+(define (split-at-predicate pred lst)
+ "Split LST into two lists at the first element that returns #f for
+ (PRED previous_element element). Return the two parts as a pair.
+ Example: (split-at-predicate < '(1 2 3 2 1)) ==> ((1 2 3) . (2 1))"
+ (if (null? lst)
+ (list lst)
+ (let ((i (list-index pred (cdr lst) lst)))
+ (if i
+ (cons (take lst (1+ i)) (drop lst (1+ i)))
+ (list lst)))))
+
+(define-public (split-list-by-separator lst pred)
+ "Split LST at each element that satisfies PRED, and return the parts
+ (with the separators removed) as a list of lists. Example:
+ (split-list-by-separator '(a 0 b c 1 d) number?) ==> ((a) (b c) (d))"
+ (let loop ((result '()) (lst lst))
+ (if (and lst (not (null? lst)))
+ (loop
+ (append result
+ (list (take-while (lambda (x) (not (pred x))) lst)))
+ (let ((tail (find-tail pred lst)))
+ (if tail (cdr tail) #f)))
+ result)))
(define-public (offset-add a b)
(cons (+ (car a) (car b))
(string-append (ly:number->string (car c)) " "
(ly:number->string (cdr c))))
+(define-public (dir-basename file . rest)
+ "Strip suffixes in REST, but leave directory component for FILE."
+ (define (inverse-basename x y) (basename y x))
+ (simple-format #f "~a/~a" (dirname file)
+ (fold inverse-basename file rest)))
(define-public (write-me message x)
"Return X. Display MESSAGE and write X. Handy for debugging,
;; don't confuse users with #<procedure .. > syntax.
;;
(define-public (scm->string val)
- (if (and (procedure? val) (symbol? (procedure-name val)))
+ (if (and (procedure? val)
+ (symbol? (procedure-name val)))
(symbol->string (procedure-name val))
(string-append
- (if (self-evaluating? val) "" "'")
- (call-with-output-string (lambda (port) (display val port))))))
+ (if (self-evaluating? val)
+ (if (string? val)
+ "\""
+ "")
+ "'")
+ (call-with-output-string (lambda (port) (display val port)))
+ (if (string? val)
+ "\""
+ ""))))
(define-public (!= lst r)
(not (= lst r)))
(define-public (version-not-seen-message input-file-name)
(ly:message
- "~a:0: ~a: ~a"
+ "~a:0: ~a ~a"
input-file-name
- (_ "warning: ")
+ (_ "warning:")
(format #f
(_ "no \\version statement found, please add~afor future compatibility")
(format #f "\n\n\\version ~s\n\n" (lilypond-version)))))
(define-public (old-relative-not-used-message input-file-name)
(ly:message
- "~a:0: ~a: ~a"
+ "~a:0: ~a ~a"
input-file-name
- (_ "warning: ")
+ (_ "warning:")
(_ "old relative compatibility not used")))