X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=scm%2Flily-library.scm;h=ae13bbebf0ec748142485952847b75a2d1273587;hb=acb0f57f5829647a48ffc5d81b8b3246e20863f8;hp=e8327e4bed7e526e32dc4d8f85e916459aaac456;hpb=da5f5b336361797ac948636827bba03ecb73f874;p=lilypond.git diff --git a/scm/lily-library.scm b/scm/lily-library.scm index e8327e4bed..ae13bbebf0 100644 --- a/scm/lily-library.scm +++ b/scm/lily-library.scm @@ -3,9 +3,11 @@ ;;;; ;;;; source file of the GNU LilyPond music typesetter ;;;; -;;;; (c) 1998--2006 Jan Nieuwenhuizen +;;;; (c) 1998--2007 Jan Nieuwenhuizen ;;;; Han-Wen Nienhuys +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; constants. (define-public X 0) (define-public Y 1) @@ -17,57 +19,93 @@ (define-public DOWN -1) (define-public CENTER 0) -(define-safe-public DOUBLE-FLAT -4) -(define-safe-public THREE-Q-FLAT -3) -(define-safe-public FLAT -2) -(define-safe-public SEMI-FLAT -1) +(define-safe-public DOUBLE-FLAT-QTS -4) +(define-safe-public THREE-Q-FLAT-QTS -3) +(define-safe-public FLAT-QTS -2) +(define-safe-public SEMI-FLAT-QTS -1) +(define-safe-public NATURAL-QTS 0) +(define-safe-public SEMI-SHARP-QTS 1) +(define-safe-public SHARP-QTS 2) +(define-safe-public THREE-Q-SHARP-QTS 3) +(define-safe-public DOUBLE-SHARP-QTS 4) +(define-safe-public SEMI-TONE-QTS 2) + +(define-safe-public DOUBLE-FLAT -1) +(define-safe-public THREE-Q-FLAT -3/4) +(define-safe-public FLAT -1/2) +(define-safe-public SEMI-FLAT -1/4) (define-safe-public NATURAL 0) -(define-safe-public SEMI-SHARP 1) -(define-safe-public SHARP 2) -(define-safe-public THREE-Q-SHARP 3) -(define-safe-public DOUBLE-SHARP 4) -(define-safe-public SEMI-TONE 2) +(define-safe-public SEMI-SHARP 1/4) +(define-safe-public SHARP 1/2) +(define-safe-public THREE-Q-SHARP 3/4) +(define-safe-public DOUBLE-SHARP 1) +(define-safe-public SEMI-TONE 1/2) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; moments (define-public ZERO-MOMENT (ly:make-moment 0 1)) (define-public (moment-min a b) (if (ly:moment output hooks. -;; parser stuff. -(define-public (print-music-as-book parser music) - (let* ((head (ly:parser-lookup parser '$defaultheader)) - (book (ly:make-book (ly:parser-lookup parser '$defaultpaper) - head (scorify-music music parser)))) - (print-book-with-defaults parser book))) - -(define-public (print-score-as-book parser score) - (let* ((head (ly:parser-lookup parser '$defaultheader)) - (book (ly:make-book (ly:parser-lookup parser '$defaultpaper) - head score))) - (print-book-with-defaults parser book))) - -(define-public (print-score parser score) - (let* ((head (ly:parser-lookup parser '$defaultheader)) - (book (ly:make-book (ly:parser-lookup parser '$defaultpaper) - head score))) - (ly:parser-print-score parser book))) (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 (music-property symbol) + (let ((value (ly:music-property music symbol))) + (if (not (null? value)) + value + #f))) + (cond ((music-property 'page-marker) + ;; a page marker: set page break/turn permissions or label + (begin + (let ((label (music-property 'page-label))) + (if (symbol? label) + (score-handler (ly:make-page-label-marker label)))) + (for-each (lambda (symbol) + (let ((permission (music-property symbol))) + (if (symbol? permission) + (score-handler + (ly:make-page-permission-marker symbol + (if (eqv? 'forbid permission) + '() + permission)))))) + (list 'line-break-permission 'page-break-permission + 'page-turn-permission)))) + ((not (music-property 'void)) + ;; a regular music expression: make a score with this music + ;; void music is discarded + (score-handler (scorify-music music parser))))) + +(define-public (collect-music-for-book parser music) + "Top-level music handler" + (collect-music-aux (lambda (score) + (collect-scores-for-book parser score)) + parser + music)) + +(define-public (collect-book-music-for-book parser book music) + "Book music handler" + (collect-music-aux (lambda (score) + (ly:book-add-score! book score)) + parser + music)) (define-public (scorify-music music parser) + "Preprocess MUSIC." (for-each (lambda (func) (set! music (func music parser))) @@ -75,51 +113,37 @@ (ly:make-score music)) -(define-public (collect-music-for-book parser music) - ;; discard music if its 'void property is true. - (let ((void-music (ly:music-property music 'void))) - (if (or (null? void-music) (not void-music)) - (collect-scores-for-book parser (scorify-music music parser))))) - - -(define-public (print-book-with-defaults parser book) +(define (print-book-with parser book process-procedure) (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))) - - (if (not (integer? count)) - (set! count 0)) - - (if (> count 0) - (set! base (format #f "~a-~a" base count))) + (base (ly:parser-output-name parser)) + (output-suffix (ly:parser-lookup parser 'output-suffix)) ) - (ly:parser-define! parser 'output-count (1+ count)) - (ly:book-process book paper layout base) - )) - -(define-public (print-score-with-defaults parser score) - (let* - ((paper (ly:parser-lookup parser '$defaultpaper)) - (layout (ly:parser-lookup parser '$defaultlayout)) - (header (ly:parser-lookup parser '$defaultheader)) - (count (ly:parser-lookup parser 'output-count)) - (base (ly:parser-output-name parser))) + (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)) (set! count 0)) (if (> count 0) (set! base (format #f "~a-~a" base count))) - (ly:parser-define! parser 'output-count (1+ count)) - (ly:score-process score header paper layout base) + (process-procedure book paper layout base) )) +(define-public (print-book-with-defaults parser book) + (print-book-with parser book ly:book-process)) + +(define-public (print-book-with-defaults-as-systems parser book) + (print-book-with parser book ly:book-process-to-systems)) ;;;;;;;;;;;;;;;; ;; alist + (define-public assoc-get ly:assoc-get) (define-public (uniqued-alist alist acc) @@ -132,14 +156,6 @@ (stringstring (car x)) (symbol->string (car y)))) -(define-public (chain-assoc x alist-list) - (if (null? alist-list) - #f - (let* ((handle (assoc x (car alist-list)))) - (if (pair? handle) - handle - (chain-assoc x (cdr alist-list)))))) - (define-public (chain-assoc-get x alist-list . default) "Return ALIST entry for X. Return DEFAULT (optional, else #f) if not found." @@ -192,6 +208,7 @@ found." ;;;;;;;;;;;;;;;; ;; vector + (define-public (vector-for-each proc vec) (do ((i 0 (1+ i))) @@ -201,24 +218,9 @@ found." ;;;;;;;;;;;;;;;; ;; hash -(if (not (defined? 'hash-table?)) ;; guile 1.6 compat - (begin - (define hash-table? vector?) - (define-public (hash-for-each proc tab) - (hash-fold (lambda (k v prior) - (proc k v) - #f) - #f - tab)) - (define-public (hash-table->alist t) - "Convert table t to list" - (apply append (vector->list t)))) - - ;; native hashtabs. - (begin - (define-public (hash-table->alist t) - (hash-fold (lambda (k v acc) (acons k v acc)) - '() t)))) +(define-public (hash-table->alist t) + (hash-fold (lambda (k v acc) (acons k v acc)) + '() t)) ;; todo: code dup with C++. (define-safe-public (alist->hash-table lst) @@ -230,6 +232,18 @@ found." ;;;;;;;;;;;;;;;; ;; list +(define (functional-or . rest) + (if (pair? rest) + (or (car rest) + (apply functional-and (cdr rest))) + #f)) + +(define (functional-and . rest) + (if (pair? rest) + (and (car rest) + (apply functional-and (cdr rest))) + #t)) + (define (split-list lst n) "Split LST in N equal sized parts" @@ -253,8 +267,11 @@ found." (else (helper (cdr todo) (1+ k))))) + (helper lst 0)) + (define-public (count-list lst) "Given lst (E1 E2 .. ) return ((E1 . 1) (E2 . 2) ... ) " + (define (helper l acc count) (if (pair? l) (helper (cdr l) (cons (cons (car l) count) acc) (1+ count)) @@ -291,19 +308,17 @@ found." "Return list of elements in A that are not in B." (lset-difference eq? a b)) -;; TODO: use the srfi-1 partition function. (define-public (uniq-list lst) - - "Uniq LST, assuming that it is sorted" - (define (helper acc lst) - (if (null? lst) - acc - (if (null? (cdr lst)) - (cons (car lst) acc) - (if (equal? (car lst) (cadr lst)) - (helper acc (cdr lst)) - (helper (cons (car lst) acc) (cdr lst)))))) - (reverse! (helper '() lst) '())) + "Uniq LST, assuming that it is sorted. Uses equal? for comparisons." + + (reverse! + (fold (lambda (x acc) + (if (null? acc) + (list x) + (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) @@ -312,6 +327,7 @@ found." 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) @@ -394,6 +410,9 @@ found." (define-public interval-end cdr) +(define-public (interval-bound interval dir) + ((if (= dir RIGHT) cdr car) interval)) + (define-public (interval-index interval dir) "Interpolate INTERVAL between between left (DIR=-1) and right (DIR=+1)" @@ -437,9 +456,16 @@ found." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; - - +;; string + +(define-public (string-endswith s suffix) + (equal? suffix (substring s + (max 0 (- (string-length s) (string-length suffix))) + (string-length s)))) + +(define-public (string-startswith s prefix) + (equal? prefix (substring s 0 (min (string-length s) (string-length prefix))))) + (define-public (string-encode-integer i) (cond ((= i 0) "o") @@ -448,9 +474,6 @@ found." (make-string 1 (integer->char (+ 65 (modulo i 26)))) (string-encode-integer (quotient i 26)))))) -(define-public (ly:numbers->string lst) - (string-join (map ly:number->string lst) " ")) - (define (number->octal-string x) (let* ((n (inexact->exact x)) (n64 (quotient n 64)) @@ -530,7 +553,9 @@ possibly turned off." 0 (if (< x 0) -1 1))) -(define-public (car< a b) (< (car a) (car b))) + +(define-public (car< a b) + (< (car a) (car b))) (define-public (symbolstring lst) (symbol->string r))) @@ -585,14 +610,16 @@ possibly turned off." (define-public (version-not-seen-message input-file-name) (ly:message - (string-append - input-file-name ": 0: " (_ "warning: ") - (format #f - (_ "no \\version statement found, please add~afor future compatibility") - (format #f "\n\n\\version ~s\n\n" (lilypond-version)))))) + "~a:0: ~a: ~a" + input-file-name + (_ "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 - (string-append - input-file-name ": 0: " (_ "warning: ") - (_ "old relative compatibility not used")))) + "~a:0: ~a: ~a" + input-file-name + (_ "warning: ") + (_ "old relative compatibility not used")))