(cons (ly:moment-main-numerator moment)
(ly:moment-main-denominator moment)))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; durations
+
+(define-public (duration-log-factor lognum)
+"Given a logarithmic duration number, return the length of the duration,
+as a number of whole notes."
+ (or (and (exact? lognum) (integer? lognum))
+ (scm-error 'wrong-type-arg "duration-log-factor" "Not an integer: ~S" (list lognum) #f))
+ (if (<= lognum 0)
+ (ash 1 (- lognum))
+ (/ (ash 1 lognum))))
+
+(define-public (duration-dot-factor dotcount)
+"Given a count of the dots used to extend a musical duration, return
+the numeric factor by which they increase the duration."
+ (or (and (exact? dotcount) (integer? dotcount) (>= dotcount 0))
+ (scm-error 'wrong-type-arg "duration-dot-factor" "Not a count: ~S" (list dotcount) #f))
+ (- 2 (/ (ash 1 dotcount))))
+
+(define-public (duration-length dur)
+"Return the overall length of a duration, as a number of whole notes.
+(Not to be confused with ly:duration-length, which returns a less-useful
+moment object.)"
+ (ly:moment-main (ly:duration-length dur)))
+
+(define-public (duration-visual dur)
+"Given a duration object, return the visual part of the duration (base
+note length and dot count), in the form of a duration object with
+non-visual scale factor 1."
+ (ly:make-duration (ly:duration-log dur) (ly:duration-dot-count dur) 1))
+
+(define-public (duration-visual-length dur)
+"Given a duration object, return the length of the visual part of the
+duration (base note length and dot count), as a number of whole notes."
+ (duration-length (duration-visual dur)))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; arithmetic
(define-public (average x . lst)
(define-public (collect-music-aux score-handler parser music)
(define (music-property symbol)
- (let ((value (ly:music-property music symbol)))
- (if (not (null? value))
- value
- #f)))
+ (ly:music-property music symbol #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))
+ (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 (eq? 'forbid permission)
+ '()
+ permission))))))
+ '(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 (scorify-music music parser)
"Preprocess @var{music}."
-
- (for-each (lambda (func)
- (set! music (func music parser)))
- toplevel-music-functions)
-
- (ly:make-score music))
-
+ (ly:make-score
+ (fold (lambda (f m) (f m parser))
+ music
+ toplevel-music-functions)))
(define (get-current-filename parser book)
"return any suffix value for output filename allowing for settings by
calls to bookOutputName function"
- (let ((book-filename (paper-variable parser book 'output-filename)))
- (if (not book-filename)
- (ly:parser-output-name parser)
- book-filename)))
+ (or (paper-variable parser book 'output-filename)
+ (ly:parser-output-name parser)))
(define (get-current-suffix parser book)
"return any suffix value for output filename allowing for settings by calls to
(define-public (context-mod-from-music parser music)
(let ((warn #t) (mods (ly:make-context-mod)))
- (let loop ((m music) (context #f))
+ (let loop ((m music))
(if (music-is-of-type? m 'layout-instruction-event)
- (let ((symbol (cons context (ly:music-property m 'symbol))))
+ (let ((symbol (ly:music-property m 'symbol)))
(ly:add-context-mod
mods
(case (ly:music-property m 'name)
(cons* 'push
symbol
(ly:music-property m 'grob-value)
- (ly:music-property m 'grob-property-path)))
- ((RevertProperty)
+ (cond
+ ((ly:music-property m 'grob-property #f) => list)
+ (else
+ (ly:music-property m 'grob-property-path)))))
+ ((RevertProperty)
(cons* 'pop
symbol
- (ly:music-property m 'grob-property-path))))))
+ (cond
+ ((ly:music-property m 'grob-property #f) => list)
+ (else
+ (ly:music-property m 'grob-property-path))))))))
(case (ly:music-property m 'name)
((ApplyContext)
(ly:add-context-mod mods
(list 'apply
(ly:music-property m 'procedure))))
((ContextSpeccedMusic)
- (loop (ly:music-property m 'element)
- (ly:music-property m 'context-type)))
+ (loop (ly:music-property m 'element)))
(else
(let ((callback (ly:music-property m 'elements-callback)))
(if (procedure? callback)
- (fold loop context (callback m))
+ (for-each loop (callback m))
(if (and warn (ly:duration? (ly:music-property m 'duration)))
(begin
(ly:music-warning
music
(_ "Music unsuitable for context-mod"))
- (set! warn #f))))))))
- context)
+ (set! warn #f)))))))))
mods))
(define-public (context-defs-from-music parser output-def music)
(cons* 'push
(ly:music-property m 'symbol)
(ly:music-property m 'grob-value)
- (ly:music-property m 'grob-property-path)))
+ (cond
+ ((ly:music-property m 'grob-property #f) => list)
+ (else
+ (ly:music-property m 'grob-property-path)))))
((RevertProperty)
(cons* 'pop
(ly:music-property m 'symbol)
- (ly:music-property m 'grob-property-path)))))
+ (cond
+ ((ly:music-property m 'grob-property #f) => list)
+ (else
+ (ly:music-property m 'grob-property-path)))))))
(case (ly:music-property m 'name)
((ApplyContext)
(ly:add-context-mod mods
(define-public (first-member members lst)
"Return first successful member (of member) from @var{members} in
@var{lst}."
- (if (null? members)
- #f
- (let ((m (member (car members) lst)))
- (if m m (first-member (cdr members) lst)))))
+ (any (lambda (m) (member m lst)) members))
(define-public (first-assoc keys lst)
"Return first successful assoc of key from @var{keys} in @var{lst}."
- (if (null? keys)
- #f
- (let ((k (assoc (car keys) lst)))
- (if k k (first-assoc (cdr keys) lst)))))
+ (any (lambda (k) (assoc k lst)) keys))
(define-public (flatten-alist alist)
(if (null? alist)
;; hash
(define-public (hash-table->alist t)
- (hash-fold (lambda (k v acc) (acons k v acc))
- '() t))
+ (hash-fold acons '() t))
;; todo: code dup with C++.
(define-safe-public (alist->hash-table lst)
"Convert alist to table"
(let ((m (make-hash-table (length lst))))
- (map (lambda (k-v) (hashq-set! m (car k-v) (cdr k-v))) lst)
+ (for-each (lambda (k-v) (hashq-set! m (car k-v) (cdr k-v))) lst)
m))
;;;;;;;;;;;;;;;;
;; list
(define (functional-or . rest)
- (if (pair? rest)
- (or (car rest)
- (apply functional-or (cdr rest)))
- #f))
+ (any identity rest))
(define (functional-and . rest)
- (if (pair? rest)
- (and (car rest)
- (apply functional-and (cdr rest)))
- #t))
+ (every identity rest))
(define (split-list lst n)
"Split LST in N equal sized parts"
(helper lst (make-vector n '()) (1- n)))
(define (list-element-index lst x)
- (define (helper todo k)
- (cond
- ((null? todo) #f)
- ((equal? (car todo) x) k)
- (else
- (helper (cdr todo) (1+ k)))))
-
- (helper lst 0))
+ (list-index (lambda (m) (equal? m x)) lst))
(define-public (count-list lst)
"Given @var{lst} as @code{(E1 E2 .. )}, return
@code{((E1 . 1) (E2 . 2) ... )}."
-
- (define (helper l acc count)
- (if (pair? l)
- (helper (cdr l) (cons (cons (car l) count) acc) (1+ count))
- acc))
-
-
- (reverse (helper lst '() 1)))
+ (map cons lst (iota (length lst) 1)))
(define-public (list-join lst intermediate)
"Put @var{intermediate} between all elts of @var{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 (lambda (x y) (not (pred x y)))
- lst
- (cdr lst))))
- (if i
- (cons (take lst (1+ i)) (drop lst (1+ i)))
- (list lst)))))
+ (let ((i (and (pair? lst)
+ (list-index (lambda (x y) (not (pred x y)))
+ lst
+ (cdr lst)))))
+ (if i
+ (call-with-values
+ (lambda () (split-at lst (1+ i)))
+ cons)
+ (list lst))))
(define-public (split-list-by-separator lst pred)
"Split @var{lst} at each element that satisfies @var{pred}, and return
the parts (with the separators removed) as a list of lists. For example,
executing @samp{(split-list-by-separator '(a 0 b c 1 d) number?)} returns
@samp{((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)))
+ (call-with-values (lambda () (break pred lst))
+ (lambda (head tail)
+ (cons head
+ (if (null? tail)
+ tail
+ (split-list-by-separator (cdr tail) pred))))))
(define-public (offset-add a b)
(cons (+ (car a) (car b))
(define-public (version-not-seen-message input-file-name)
(ly:warning-located
- (ly:format "~a:0" input-file-name)
+ (ly:format "~a:1" input-file-name)
(_ "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:warning-located
- (ly:format "~a:0" input-file-name)
+ (ly:format "~a:1" input-file-name)
(_ "old relative compatibility not used")))