Doc: Contributing -- add instructions on git-cl issue`
[lilypond/mpolesky.git] / scm / lily-library.scm
blob0864e57deca4271ce57dddb3f33b65e8ef8dedd2
1 ;;;; This file is part of LilyPond, the GNU music typesetter.
2 ;;;;
3 ;;;; Copyright (C) 1998--2010 Jan Nieuwenhuizen <janneke@gnu.org>
4 ;;;; Han-Wen Nienhuys <hanwen@xs4all.nl>
5 ;;;;
6 ;;;; LilyPond is free software: you can redistribute it and/or modify
7 ;;;; it under the terms of the GNU General Public License as published by
8 ;;;; the Free Software Foundation, either version 3 of the License, or
9 ;;;; (at your option) any later version.
10 ;;;;
11 ;;;; LilyPond is distributed in the hope that it will be useful,
12 ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ;;;; GNU General Public License for more details.
15 ;;;;
16 ;;;; You should have received a copy of the GNU General Public License
17 ;;;; along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
19 ; for take, drop, take-while, list-index, and find-tail:
20 (use-modules (srfi srfi-1))
22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
23 ;; constants.
25 (define-public X 0)
26 (define-public Y 1)
27 (define-safe-public START -1)
28 (define-safe-public STOP 1)
29 (define-public LEFT -1)
30 (define-public RIGHT 1)
31 (define-public UP 1)
32 (define-public DOWN -1)
33 (define-public CENTER 0)
35 (define-safe-public DOUBLE-FLAT-QTS -4)
36 (define-safe-public THREE-Q-FLAT-QTS -3)
37 (define-safe-public FLAT-QTS -2)
38 (define-safe-public SEMI-FLAT-QTS -1)
39 (define-safe-public NATURAL-QTS 0)
40 (define-safe-public SEMI-SHARP-QTS 1)
41 (define-safe-public SHARP-QTS 2)
42 (define-safe-public THREE-Q-SHARP-QTS 3)
43 (define-safe-public DOUBLE-SHARP-QTS 4)
44 (define-safe-public SEMI-TONE-QTS 2)
46 (define-safe-public DOUBLE-FLAT  -1)
47 (define-safe-public THREE-Q-FLAT -3/4)
48 (define-safe-public FLAT -1/2)
49 (define-safe-public SEMI-FLAT -1/4)
50 (define-safe-public NATURAL 0)
51 (define-safe-public SEMI-SHARP 1/4)
52 (define-safe-public SHARP 1/2)
53 (define-safe-public THREE-Q-SHARP 3/4)
54 (define-safe-public DOUBLE-SHARP 1)
55 (define-safe-public SEMI-TONE 1/2)
57 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
58 ;; moments
60 (define-public ZERO-MOMENT (ly:make-moment 0 1))
62 (define-public (moment-min a b)
63   (if (ly:moment<? a b) a b))
65 (define-public (moment<=? a b)
66   (or (equal? a b)
67       (ly:moment<? a b)))
69 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
70 ;; arithmetic
71 (define-public (average x . lst)
72   (/ (+ x (apply + lst)) (1+ (length lst))))
74 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
75 ;; parser <-> output hooks.
77 (define-public (collect-bookpart-for-book parser book-part)
78   "Toplevel book-part handler"
79   (define (add-bookpart book-part)
80     (ly:parser-define!
81        parser 'toplevel-bookparts
82        (cons book-part (ly:parser-lookup parser 'toplevel-bookparts))))
83   ;; If toplevel scores have been found before this \bookpart,
84   ;; add them first to a dedicated bookpart
85   (if (pair? (ly:parser-lookup parser 'toplevel-scores))
86       (begin
87         (add-bookpart (ly:make-book-part
88                        (ly:parser-lookup parser 'toplevel-scores)))
89         (ly:parser-define! parser 'toplevel-scores (list))))
90   (add-bookpart book-part))
92 (define-public (collect-scores-for-book parser score)
93   (ly:parser-define!
94    parser 'toplevel-scores
95    (cons score (ly:parser-lookup parser 'toplevel-scores))))
97 (define-public (collect-music-aux score-handler parser music)
98   (define (music-property symbol)
99     (let ((value (ly:music-property music symbol)))
100       (if (not (null? value))
101           value
102           #f)))
103   (cond ((music-property 'page-marker)
104          ;; a page marker: set page break/turn permissions or label
105          (begin
106            (let ((label (music-property 'page-label)))
107              (if (symbol? label)
108                  (score-handler (ly:make-page-label-marker label))))
109            (for-each (lambda (symbol)
110                        (let ((permission (music-property symbol)))
111                          (if (symbol? permission)
112                              (score-handler
113                               (ly:make-page-permission-marker symbol
114                                                               (if (eqv? 'forbid permission)
115                                                                   '()
116                                                                   permission))))))
117                      (list 'line-break-permission 'page-break-permission
118                            'page-turn-permission))))
119         ((not (music-property 'void))
120          ;; a regular music expression: make a score with this music
121          ;; void music is discarded
122          (score-handler (scorify-music music parser)))))
124 (define-public (collect-music-for-book parser music)
125   "Top-level music handler"
126   (collect-music-aux (lambda (score)
127                        (collect-scores-for-book parser score))
128                      parser
129                      music))
131 (define-public (collect-book-music-for-book parser book music)
132   "Book music handler"
133   (collect-music-aux (lambda (score)
134                        (ly:book-add-score! book score))
135                      parser
136                      music))
138 (define-public (scorify-music music parser)
139   "Preprocess MUSIC."
141   (for-each (lambda (func)
142               (set! music (func music parser)))
143             toplevel-music-functions)
145   (ly:make-score music))
148 (define (get-current-filename parser)
149   "return any suffix value for output filename allowing for settings by
150 calls to bookOutputName function"
151   (let ((book-filename (ly:parser-lookup parser 'book-filename)))
152     (if (not book-filename)
153         (ly:parser-output-name parser)
154         book-filename)))
156 (define (get-current-suffix parser)
157   "return any suffix value for output filename allowing for settings by calls to
158 bookoutput function"
159   (let ((book-output-suffix (ly:parser-lookup parser 'book-output-suffix)))
160     (if (not (string? book-output-suffix))
161         (ly:parser-lookup parser 'output-suffix)
162         book-output-suffix)))
164 (define-public current-outfile-name #f)  ; for use by regression tests
166 (define (get-outfile-name parser)
167   "return current filename for generating backend output files"
168   ;; user can now override the base file name, so we have to use
169   ;; the file-name concatenated with any potential output-suffix value
170   ;; as the key to out internal a-list
171   (let* ((base-name (get-current-filename parser))
172          (output-suffix (get-current-suffix parser))
173          (alist-key (format "~a~a" base-name output-suffix))
174          (counter-alist (ly:parser-lookup parser 'counter-alist))
175          (output-count (assoc-get alist-key counter-alist 0))
176          (result base-name))
177     ;; Allow all ASCII alphanumerics, including accents
178     (if (string? output-suffix)
179         (set! result
180               (format "~a-~a"
181                       result
182                       (string-regexp-substitute
183                        "[^-[:alnum:]]"
184                        "_"
185                        output-suffix))))
187     ;; assoc-get call will always have returned a number
188     (if (> output-count 0)
189         (set! result (format #f "~a-~a" result output-count)))
191     (ly:parser-define!
192      parser 'counter-alist
193      (assoc-set! counter-alist alist-key (1+ output-count)))
194     (set! current-outfile-name result)
195     result))
197 (define (print-book-with parser book process-procedure)
198   (let* ((paper (ly:parser-lookup parser '$defaultpaper))
199          (layout (ly:parser-lookup parser '$defaultlayout))
200          (outfile-name (get-outfile-name parser)))
201     (process-procedure book paper layout outfile-name)))
203 (define-public (print-book-with-defaults parser book)
204   (print-book-with parser book ly:book-process))
206 (define-public (print-book-with-defaults-as-systems parser book)
207   (print-book-with parser book ly:book-process-to-systems))
209 ;; Add a score to the current bookpart, book or toplevel
210 (define-public (add-score parser score)
211     (cond
212       ((ly:parser-lookup parser '$current-bookpart)
213           ((ly:parser-lookup parser 'bookpart-score-handler)
214                 (ly:parser-lookup parser '$current-bookpart) score))
215       ((ly:parser-lookup parser '$current-book)
216           ((ly:parser-lookup parser 'book-score-handler)
217                 (ly:parser-lookup parser '$current-book) score))
218       (else
219           ((ly:parser-lookup parser 'toplevel-score-handler) parser score))))
221 (define-public (add-text parser text)
222   (add-score parser (list text)))
224 (define-public (add-music parser music)
225   (collect-music-aux (lambda (score)
226                        (add-score parser score))
227                      parser
228                      music))
231 ;;;;;;;;;;;;;;;;
232 ;; alist
234 (define-public assoc-get ly:assoc-get)
236 (define-public chain-assoc-get ly:chain-assoc-get)
238 (define-public (uniqued-alist alist acc)
239   (if (null? alist) acc
240       (if (assoc (caar alist) acc)
241           (uniqued-alist (cdr alist) acc)
242           (uniqued-alist (cdr alist) (cons (car alist) acc)))))
244 (define-public (alist<? x y)
245   (string<? (symbol->string (car x))
246             (symbol->string (car y))))
248 (define (map-alist-vals func list)
249   "map FUNC over the vals of  LIST, leaving the keys."
250   (if (null?  list)
251       '()
252       (cons (cons  (caar list) (func (cdar list)))
253             (map-alist-vals func (cdr list)))))
255 (define (map-alist-keys func list)
256   "map FUNC over the keys of an alist LIST, leaving the vals. "
257   (if (null?  list)
258       '()
259       (cons (cons (func (caar list)) (cdar list))
260             (map-alist-keys func (cdr list)))))
262 (define-public (first-member members lst)
263   "Return first successful MEMBER of member from MEMBERS in LST."
264   (if (null? members)
265       #f
266       (let ((m (member (car members) lst)))
267         (if m m (first-member (cdr members) lst)))))
269 (define-public (first-assoc keys lst)
270   "Return first successful ASSOC of key from KEYS in LST."
271   (if (null? keys)
272       #f
273       (let ((k (assoc (car keys) lst)))
274         (if k k (first-assoc (cdr keys) lst)))))
276 (define-public (flatten-alist alist)
277   (if (null? alist)
278       '()
279       (cons (caar alist)
280             (cons (cdar alist)
281                   (flatten-alist (cdr alist))))))
283 ;;;;;;;;;;;;;;;;
284 ;; vector
286 (define-public (vector-for-each proc vec)
287   (do
288       ((i 0 (1+ i)))
289       ((>= i (vector-length vec)) vec)
290     (vector-set! vec i (proc (vector-ref vec i)))))
292 ;;;;;;;;;;;;;;;;
293 ;; hash
295 (define-public (hash-table->alist t)
296   (hash-fold (lambda (k v acc) (acons  k v  acc))
297              '() t))
299 ;; todo: code dup with C++.
300 (define-safe-public (alist->hash-table lst)
301   "Convert alist to table"
302   (let ((m (make-hash-table (length lst))))
303     (map (lambda (k-v) (hashq-set! m (car k-v) (cdr k-v))) lst)
304     m))
306 ;;;;;;;;;;;;;;;;
307 ;; list
309 (define (functional-or . rest)
310   (if (pair? rest)
311       (or (car rest)
312            (apply functional-or (cdr rest)))
313       #f))
315 (define (functional-and . rest)
316   (if (pair? rest)
317       (and (car rest)
318            (apply functional-and (cdr rest)))
319       #t))
321 (define (split-list lst n)
322   "Split LST in N equal sized parts"
324   (define (helper todo acc-vector k)
325     (if (null? todo)
326         acc-vector
327         (begin
328           (if (< k 0)
329               (set! k (+ n k)))
331           (vector-set! acc-vector k (cons (car todo) (vector-ref acc-vector k)))
332           (helper (cdr todo) acc-vector (1- k)))))
334   (helper lst (make-vector n '()) (1- n)))
336 (define (list-element-index lst x)
337   (define (helper todo k)
338     (cond
339      ((null? todo) #f)
340      ((equal? (car todo) x) k)
341      (else
342       (helper (cdr todo) (1+ k)))))
344   (helper lst 0))
346 (define-public (count-list lst)
347   "Given lst (E1 E2 .. ) return ((E1 . 1) (E2 . 2) ... )  "
349   (define (helper l acc count)
350     (if (pair? l)
351         (helper (cdr l) (cons (cons (car l) count) acc) (1+ count))
352         acc))
355   (reverse (helper lst '() 1)))
357 (define-public (list-join lst intermediate)
358   "put INTERMEDIATE  between all elts of LST."
360   (fold-right
361    (lambda (elem prev)
362             (if (pair? prev)
363                 (cons  elem (cons intermediate prev))
364                 (list elem)))
365           '() lst))
367 (define-public (filtered-map proc lst)
368   (filter
369    (lambda (x) x)
370    (map proc lst)))
372 (define (flatten-list x)
373   "Unnest list."
374   (cond ((null? x) '())
375         ((not (pair? x)) (list x))
376         (else (append (flatten-list (car x))
377                       (flatten-list (cdr x))))))
379 (define (list-minus a b)
380   "Return list of elements in A that are not in B."
381   (lset-difference eq? a b))
383 (define-public (uniq-list lst)
384   "Uniq LST, assuming that it is sorted. Uses equal? for comparisons."
386   (reverse!
387    (fold (lambda (x acc)
388            (if (null? acc)
389                (list x)
390                (if (equal? x (car acc))
391                    acc
392                    (cons x acc))))
393          '() lst) '()))
395 (define (split-at-predicate pred lst)
396   "Split LST into two lists at the first element that returns #f for
397   (PRED previous_element element). Return the two parts as a pair.
398   Example: (split-at-predicate < '(1 2 3 2 1)) ==> ((1 2 3) . (2 1))"
399   (if (null? lst)
400       (list lst)
401       (let ((i (list-index (lambda (x y) (not (pred x y)))
402                            lst
403                            (cdr lst))))
404         (if i
405             (cons (take lst (1+ i)) (drop lst (1+ i)))
406             (list lst)))))
408 (define-public (split-list-by-separator lst pred)
409   "Split LST at each element that satisfies PRED, and return the parts
410   (with the separators removed) as a list of lists. Example:
411   (split-list-by-separator '(a 0 b c 1 d) number?) ==> ((a) (b c) (d))"
412   (let loop ((result '()) (lst lst))
413     (if (and lst (not (null? lst)))
414         (loop
415           (append result
416                   (list (take-while (lambda (x) (not (pred x))) lst)))
417           (let ((tail (find-tail pred lst)))
418             (if tail (cdr tail) #f)))
419        result)))
421 (define-public (offset-add a b)
422   (cons (+ (car a) (car b))
423         (+ (cdr a) (cdr b))))
425 (define-public (offset-flip-y o)
426   (cons (car o) (- (cdr o))))
428 (define-public (offset-scale o scale)
429   (cons (* (car o) scale)
430         (* (cdr o) scale)))
432 (define-public (ly:list->offsets accum coords)
433   (if (null? coords)
434       accum
435       (cons (cons (car coords) (cadr coords))
436             (ly:list->offsets accum (cddr coords)))))
438 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
439 ;; intervals
441 (define-public empty-interval '(+inf.0 . -inf.0))
443 (define-public (symmetric-interval expr)
444   (cons (- expr) expr))
446 (define-public (interval-length x)
447   "Length of the number-pair X, when an interval"
448   (max 0 (- (cdr x) (car x))))
450 (define-public (ordered-cons a b)
451   (cons (min a b)
452         (max a b)))
454 (define-public (interval-bound interval dir)
455   ((if (= dir RIGHT) cdr car) interval))
457 (define-public (interval-index interval dir)
458   "Interpolate INTERVAL between between left (DIR=-1) and right (DIR=+1)"
460   (* (+  (interval-start interval) (interval-end interval)
461          (* dir (- (interval-end interval) (interval-start interval))))
462      0.5))
464 (define-public (interval-center x)
465   "Center the number-pair X, when an interval"
466   (if (interval-empty? x)
467       0.0
468       (/ (+ (car x) (cdr x)) 2)))
470 (define-public interval-start car)
472 (define-public interval-end cdr)
474 (define-public (interval-translate iv amount)
475   (cons (+ amount (car iv))
476         (+ amount (cdr iv))))
478 (define (other-axis a)
479   (remainder (+ a 1) 2))
481 (define-public (interval-widen iv amount)
482    (cons (- (car iv) amount)
483          (+ (cdr iv) amount)))
485 (define-public (interval-empty? iv)
486    (> (car iv) (cdr iv)))
488 (define-public (interval-union i1 i2)
489    (cons (min (car i1) (car i2))
490          (max (cdr i1) (cdr i2))))
492 (define-public (interval-intersection i1 i2)
493    (cons (max (car i1) (car i2))
494          (min (cdr i1) (cdr i2))))
496 (define-public (interval-sane? i)
497   (not (or  (nan? (car i))
498             (inf? (car i))
499             (nan? (cdr i))
500             (inf? (cdr i))
501             (> (car i) (cdr i)))))
503 (define-public (add-point interval p)
504   (cons (min (interval-start interval) p)
505         (max (interval-end interval) p)))
507 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
508 ;; string
510 (define-public (string-endswith s suffix)
511   (equal? suffix (substring s
512                             (max 0 (- (string-length s) (string-length suffix)))
513                             (string-length s))))
515 (define-public (string-startswith s prefix)
516   (equal? prefix (substring s 0 (min (string-length s) (string-length prefix)))))
518 (define-public (string-encode-integer i)
519   (cond
520    ((= i  0) "o")
521    ((< i 0)   (string-append "n" (string-encode-integer (- i))))
522    (else (string-append
523           (make-string 1 (integer->char (+ 65 (modulo i 26))))
524           (string-encode-integer (quotient i 26))))))
526 (define (number->octal-string x)
527   (let* ((n (inexact->exact x))
528          (n64 (quotient n 64))
529          (n8 (quotient (- n (* n64 64)) 8)))
530     (string-append
531      (number->string n64)
532      (number->string n8)
533      (number->string (remainder (- n (+ (* n64 64) (* n8 8))) 8)))))
535 (define-public (ly:inexact->string x radix)
536   (let ((n (inexact->exact x)))
537     (number->string n radix)))
539 (define-public (ly:number-pair->string c)
540   (string-append (ly:number->string (car c)) " "
541                  (ly:number->string (cdr c))))
543 (define-public (dir-basename file . rest)
544   "Strip suffixes in REST, but leave directory component for FILE."
545   (define (inverse-basename x y) (basename y x))
546   (simple-format #f "~a/~a" (dirname file)
547                  (fold inverse-basename file rest)))
549 (define-public (write-me message x)
550   "Return X.  Display MESSAGE and write X.  Handy for debugging,
551 possibly turned off."
552   (display message) (write x) (newline) x)
553 ;;  x)
555 (define-public (stderr string . rest)
556   (apply format (cons (current-error-port) (cons string rest)))
557   (force-output (current-error-port)))
559 (define-public (debugf string . rest)
560   (if #f
561       (apply stderr (cons string rest))))
563 (define (index-cell cell dir)
564   (if (equal? dir 1)
565       (cdr cell)
566       (car cell)))
568 (define (cons-map f x)
569   "map F to contents of X"
570   (cons (f (car x)) (f (cdr x))))
572 (define-public (list-insert-separator lst between)
573   "Create new list, inserting BETWEEN between elements of LIST"
574   (define (conc x y )
575     (if (eq? y #f)
576         (list x)
577         (cons x  (cons between y))))
578   (fold-right conc #f lst))
580 (define-public (string-regexp-substitute a b str)
581   (regexp-substitute/global #f a str 'pre b 'post))
583 (define (regexp-split str regex)
584   (define matches '())
585   (define end-of-prev-match 0)
586   (define (notice match)
588     (set! matches (cons (substring (match:string match)
589                                    end-of-prev-match
590                                    (match:start match))
591                         matches))
592     (set! end-of-prev-match (match:end match)))
594   (regexp-substitute/global #f regex str notice 'post)
596   (if (< end-of-prev-match (string-length str))
597       (set!
598        matches
599        (cons (substring str end-of-prev-match (string-length str)) matches)))
601    (reverse matches))
603 ;;;;;;;;;;;;;;;;
604 ;; other
606 (define (sign x)
607   (if (= x 0)
608       0
609       (if (< x 0) -1 1)))
611 (define-public (binary-search start end getter target-val)
612   (_i "Find the index between @var{start} and @var{end} (an integer)
613 which will produce the closest match to @var{target-val} when
614 applied to function @var{getter}.")
615   (if (<= end start)
616       start
617       (let* ((compare (quotient (+ start end) 2))
618              (get-val (getter compare)))
619         (cond
620          ((< target-val get-val)
621           (set! end (1- compare)))
622          ((< get-val target-val)
623           (set! start (1+ compare))))
624         (binary-search start end getter target-val))))
626 (define-public (car< a b)
627   (< (car a) (car b)))
629 (define-public (symbol<? lst r)
630   (string<? (symbol->string lst) (symbol->string r)))
632 (define-public (symbol-key<? lst r)
633   (string<? (symbol->string (car lst)) (symbol->string (car r))))
635 (define-public (eval-carefully symbol module . default)
636   "Check if all symbols in expr SYMBOL are reachable
637    in module MODULE. In that case evaluate, otherwise
638    print a warning and set an optional DEFAULT."
639   (let* ((unavailable? (lambda (sym)
640                          (not (module-defined? module sym))))
641          (sym-unavailable (if (pair? symbol)
642                               (filter
643                                 unavailable?
644                                 (filter symbol? (flatten-list symbol)))
645                               (if (unavailable? symbol)
646                                    #t
647                                    '()))))
648     (if (null? sym-unavailable)
649         (eval symbol module)
650         (let* ((def (and (pair? default) (car default))))
651           (ly:programming-error
652             "cannot evaluate ~S in module ~S, setting to ~S"
653             (object->string symbol)
654             (object->string module)
655             (object->string def))
656           def))))
659 ;; don't confuse users with #<procedure .. > syntax.
661 (define-public (scm->string val)
662   (if (and (procedure? val)
663            (symbol? (procedure-name val)))
664       (symbol->string (procedure-name val))
665       (string-append
666        (if (self-evaluating? val)
667            (if (string? val)
668                "\""
669                "")
670            "'")
671        (call-with-output-string (lambda (port) (display val port)))
672        (if (string? val)
673            "\""
674            ""))))
676 (define-public (!= lst r)
677   (not (= lst r)))
679 (define-public lily-unit->bigpoint-factor
680   (cond
681    ((equal? (ly:unit) "mm") (/ 72.0 25.4))
682    ((equal? (ly:unit) "pt") (/ 72.0 72.27))
683    (else (ly:error (_ "unknown unit: ~S") (ly:unit)))))
685 (define-public lily-unit->mm-factor
686   (* 25.4 (/ lily-unit->bigpoint-factor 72)))
688 ;;; FONT may be font smob, or pango font string...
689 (define-public (font-name-style font)
690   (if (string? font)
691       (string-downcase font)
692       (let* ((font-name (ly:font-name font))
693              (full-name (if font-name font-name (ly:font-file-name font))))
694           (string-downcase full-name))))
696 (define-public (modified-font-metric-font-scaling font)
697   (let* ((designsize (ly:font-design-size font))
698          (magnification (* (ly:font-magnification font)))
699          (scaling (* magnification designsize)))
700     (debugf "scaling:~S\n" scaling)
701     (debugf "magnification:~S\n" magnification)
702     (debugf "design:~S\n" designsize)
703     scaling))
705 (define-public (version-not-seen-message input-file-name)
706   (ly:message
707    "~a:0: ~a ~a"
708     input-file-name
709     (_ "warning:")
710     (format #f
711             (_ "no \\version statement found, please add~afor future compatibility")
712             (format #f "\n\n\\version ~s\n\n" (lilypond-version)))))
714 (define-public (old-relative-not-used-message input-file-name)
715   (ly:message
716    "~a:0: ~a ~a"
717     input-file-name
718     (_ "warning:")
719     (_ "old relative compatibility not used")))