From: Mark Polesky <markpolesky@yahoo.com> Date: Fri, 7 May 2010 23:56:26 +0000 (-0700) Subject: Doc & scm/: Music-functions and type-predicates. X-Git-Tag: release/2.13.21-1~19 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=eb98dcb8ece687486640a5dc3ec3aa2395ec31cf;p=lilypond.git Doc & scm/: Music-functions and type-predicates. - Clean up: NR 5.6 "Using music functions" EL 2.1 "Music functions" - In Extending 2.1, move `Void functions' to end of section, so `Functions without arguments' comes first. - Use a consistent indentation format for music functions. - Make some minor formatting/wording changes. - Categorize predicates in type-p-name-alist. - Create type-predicates-doc-string to document type-p-name-alist automatically. - Add notation appendix `Predefined type predicates' to include type-predicates-doc-string. - Show predicate name instead of "unknown" in type-check error message (provided by Neil Puttock). - Make `color?' predicate more specific. --- diff --git a/Documentation/extending/programming-interface.itely b/Documentation/extending/programming-interface.itely index 7045b49daf..7c8b287552 100644 --- a/Documentation/extending/programming-interface.itely +++ b/Documentation/extending/programming-interface.itely @@ -30,137 +30,85 @@ not familiar with Scheme, you may wish to read our @node Music functions @section Music functions -Music functions are scheme functions that are used to -automatically create music expressions. They can be used to -greatly simplify the input file. +@emph{Music functions} are scheme procedures that can create music +expressions automatically, and can be used to greatly simplify the +input file. @menu * Music function syntax:: * Simple substitution functions:: * Intermediate substitution functions:: * Mathematics in functions:: -* Void functions:: * Functions without arguments:: +* Void functions:: @end menu + @node Music function syntax @subsection Music function syntax -The general syntax of a music function is: +The general form for music functions is: @example -myFunction = -#(define-music-function (parser location @var{var_1} @var{var_2}...@var{var_n}) - (@var{var_1-type?} @var{var_2-type?}...@var{var_n-type?}) - @var{...valid music expression...}) +function = +#(define-music-function + (parser location @var{arg1} @var{arg2} @dots{}) + (@var{type1?} @var{type2?} @dots{}) + @var{music}) @end example @noindent where @multitable @columnfractions .33 .66 -@item @var{var_i} @tab @var{i}th variable -@item @var{var_i-type?} @tab type of @var{i}th variable -@item @var{...valid music expression...} @tab expression that returns -valid music, generally in the form of a Scheme expression. There is -also special syntax that allows LilyPond input code in this music -expression. -@end multitable +@item @code{@var{argN}} +@tab @var{n}th argument -The variable type checkers are scheme procedures that will return -@code{#t} if a variable is of a given type. Some common types -are shown in the table below. Other types can be found in the files -@file{lily/music-scheme.cc} and @file{scm/c++.scm}. The complete -list of named type checkers for LilyPond is found in the -@var{type-p-name-alist} of @file{scm/lily.scm}. +@item @code{@var{typeN?}} +@tab a scheme @emph{type predicate} for which @code{@var{argN}} +must return @code{#t}. -@c TODO -- automatically document type-p-name-alist +@item @code{@var{music}} +@tab A music expression, optionally written in scheme, with any +LilyPond code enclosed in hashed braces +(@tie{}@w{@code{#@{@dots{}#@}}}@tie{}). Within LilyPond code +blocks, use @code{$} to reference function arguments (eg., +@samp{$arg1}) or to start an inline scheme expression containing +function arguments (eg., @w{@samp{$(cons arg1 arg2)}}). -@multitable @columnfractions .33 .66 -@headitem Input type @tab @var{vari-type?} notation -@item Integer @tab @code{integer?} -@item Float (decimal number) @tab @code{number?} -@item Text string @tab @code{string?} -@item Markup @tab @code{markup?} -@item Music expression @tab @code{ly:music?} -@item A pair of variables @tab @code{pair?} @end multitable -The @code{parser} and @code{location} arguments are mandatory. -The @code{parser} argument is used in the body of the function -to gain access to the value of another LilyPond variable. -The @code{location} argument is used to set the @q{origin} -of the music expression that is built by the music function, -so that in case of a syntax error LilyPond -can tell the user an appropriate place to look in the input file. - -@node Simple substitution functions -@subsection Simple substitution functions +@noindent +For a list of available type predicates, see +@ruser{Predefined type predicates}. User-defined type predicates +are also allowed. -A simple substitution function is a music function whose output music -expression is written in LilyPond code, but with an input variable -substituted into the LilyPond code. The general form of these functions is -@example -myFunction = -#(define-music-function (parser location @var{var1}) - (@var{var1-type?}) - #@{ - @emph{... LilyPond input code with} @code{#$var1} @emph{for substition ...} - #@}) -@end example +@seealso -Note that the special characters @code{#@{} and @code{#@}} surround the -LilyPond music. +Notation Reference: +@ruser{Predefined type predicates}. -@multitable @columnfractions .33 .66 -@item @var{vari} @tab @var{i}th variable -@item @var{vari-type?} @tab type of @var{i}th variable -@item @var{...music...} @tab normal LilyPond input, using - variables as @code{#$var1}, etc. -@end multitable +Installed Files: +@file{lily/music-scheme.cc}, +@file{scm/c++.scm}, +@file{scm/lily.scm}. -For example, a function can be defined that simplifies -setting the padding of a TextScript: -@lilypond[quote,verbatim,ragged-right] -padText = #(define-music-function (parser location padding) (number?) - #{ - \once \override TextScript #'padding = #$padding - #}) - -\relative c''' { - c4^"piu mosso" b a b - \padText #1.8 - c4^"piu mosso" d e f - \padText #2.6 - c4^"piu mosso" fis a g -} -@end lilypond +@node Simple substitution functions +@subsection Simple substitution functions -In addition to numbers, we can use music expressions such -as notes for arguments to music functions: +Simple substitution functions are music functions whose output +music expression is written in LilyPond format and contains +function arguments in the output expression. They are described +in @ruser{Substitution function examples}. -@lilypond[quote,verbatim,ragged-right] -custosNote = #(define-music-function (parser location note) - (ly:music?) - #{ - \once \override Voice.NoteHead #'stencil = - #ly:text-interface::print - \once \override Voice.NoteHead #'text = - \markup \musicglyph #"custodes.mensural.u0" - \once \override Voice.Stem #'stencil = ##f - $note - #}) -@end lilypond @node Intermediate substitution functions @subsection Intermediate substitution functions -Slightly more complicated than simple substitution function, -intermediate substitution functions involve a mix of Scheme code and -LilyPond code in the music expression to be -returned. +Intermediate substitution functions involve a mix of Scheme code +and LilyPond code in the music expression to be returned. Some @code{\override} commands require an argument consisting of a pair of numbers (called a @code{cons cell} in Scheme). @@ -168,20 +116,19 @@ a pair of numbers (called a @code{cons cell} in Scheme). The pair can be directly passed into the music function, using a @code{pair?} variable: -@quotation @example manualBeam = -#(define-music-function (parser location beg-end) - (pair?) -#@{ - \once \override Beam #'positions = #$beg-end -#@}) +#(define-music-function + (parser location beg-end) + (pair?) + #@{ + \once \override Beam #'positions = $beg-end + #@}) \relative c' @{ \manualBeam #'(3 . 6) c8 d e f @} @end example -@end quotation Alternatively, the numbers making up the pair can be passed as separate arguments, and the Scheme code @@ -190,11 +137,12 @@ music expression: @lilypond[quote,verbatim,ragged-right] manualBeam = -#(define-music-function (parser location beg end) - (number? number?) -#{ - \once \override Beam #'positions = #(cons $beg $end) -#}) +#(define-music-function + (parser location beg end) + (number? number?) + #{ + \once \override Beam #'positions = $(cons beg end) + #}) \relative c' { \manualBeam #3 #6 c8 d e f @@ -209,61 +157,50 @@ Music functions can involve Scheme programming in addition to simple substitution, @lilypond[quote,verbatim,ragged-right] -AltOn = #(define-music-function (parser location mag) (number?) - #{ \override Stem #'length = #$(* 7.0 mag) +AltOn = +#(define-music-function + (parser location mag) + (number?) + #{ + \override Stem #'length = $(* 7.0 mag) \override NoteHead #'font-size = - #$(inexact->exact (* (/ 6.0 (log 2.0)) (log mag))) #}) + $(inexact->exact (* (/ 6.0 (log 2.0)) (log mag))) + #}) AltOff = { \revert Stem #'length \revert NoteHead #'font-size } -{ c'2 \AltOn #0.5 c'4 c' - \AltOn #1.5 c' c' \AltOff c'2 } +\relative c' { + c2 \AltOn #0.5 c4 c + \AltOn #1.5 c c \AltOff c2 +} @end lilypond @noindent This example may be rewritten to pass in music expressions, @lilypond[quote,verbatim,ragged-right] -withAlt = #(define-music-function (parser location mag music) (number? ly:music?) - #{ \override Stem #'length = #$(* 7.0 mag) +withAlt = +#(define-music-function + (parser location mag music) + (number? ly:music?) + #{ + \override Stem #'length = $(* 7.0 mag) \override NoteHead #'font-size = - #$(inexact->exact (* (/ 6.0 (log 2.0)) (log mag))) + $(inexact->exact (* (/ 6.0 (log 2.0)) (log mag))) $music \revert Stem #'length - \revert NoteHead #'font-size #}) + \revert NoteHead #'font-size + #}) -{ c'2 \withAlt #0.5 {c'4 c'} - \withAlt #1.5 {c' c'} c'2 } +\relative c' { + c2 \withAlt #0.5 { c4 c } + \withAlt #1.5 { c c } c2 +} @end lilypond -@node Void functions -@subsection Void functions - -A music function must return a music expression, but sometimes we -may want to have a function that does not involve music (such as -turning off Point and Click). To do this, we return a @code{void} -music expression. - -That is why the form -that is returned is the @code{(make-music ...)}. With the -@code{'void} property set to @code{#t}, the parser is told to -actually disregard this returned music -expression. Thus the important part of the void music function is the -processing done by the function, not the music expression that is -returned. - -@example -noPointAndClick = -#(define-music-function (parser location) () - (ly:set-option 'point-and-click #f) - (make-music 'SequentialMusic 'void #t)) -... -\noPointAndClick % disable point and click -@end example - @node Functions without arguments @subsection Functions without arguments @@ -280,7 +217,9 @@ without arguments, @example displayBarNum = -#(define-music-function (parser location) () +#(define-music-function + (parser location) + () (if (eq? #t (ly:get-option 'display-bar-numbers)) #@{ \once \override Score.BarNumber #'break-visibility = ##f #@} #@{#@})) @@ -294,6 +233,32 @@ lilypond -d display-bar-numbers FILENAME.ly @end example +@node Void functions +@subsection Void functions + +A music function must return a music expression, but sometimes we +may want to have a function that does not involve music (such as +turning off Point and Click). To do this, we return a @code{void} +music expression. + +That is why the form that is returned is the +@w{@code{(make-music @dots{})}}. With the @code{'void} property +set to @code{#t}, the parser is told to actually disregard this +returned music expression. Thus the important part of the void +music function is the processing done by the function, not the +music expression that is returned. + +@example +noPointAndClick = +#(define-music-function + (parser location) + () + (ly:set-option 'point-and-click #f) + (make-music 'SequentialMusic 'void #t)) +... +\noPointAndClick % disable point and click +@end example + @node Markup functions @section Markup functions diff --git a/Documentation/notation/changing-defaults.itely b/Documentation/notation/changing-defaults.itely index e743ac1683..bbf6a4e0b2 100644 --- a/Documentation/notation/changing-defaults.itely +++ b/Documentation/notation/changing-defaults.itely @@ -3572,16 +3572,15 @@ of ties as required. @c TODO -- add @seealso, etc. to these subsections -Where tweaks need to be reused with different music expressions, it -is often convenient to make the tweak part of a music function. -In this section, we discuss only @emph{substitution} functions, where -the object is to substitute a variable into a piece of LilyPond -input code. Other more complex functions are described in -@rextend{Music functions}. +Where tweaks need to be reused with different music expressions, +it is often convenient to make the tweak part of a @emph{music +function}. In this section, we discuss only @emph{substitution} +functions, where the object is to substitute a variable into a +piece of LilyPond input code. Other more complex functions are +described in @rextend{Music functions}. @menu * Substitution function syntax:: -* Common argument types:: * Substitution function examples:: @end menu @@ -3593,91 +3592,88 @@ code is easy. The general form of these functions is @example function = -#(define-music-function (parser location @var{var1} @var{var2}...@var{vari}... ) - (@var{var1-type?} @var{var2-type?}...@var{vari-type?}...) - #@{ - @emph{...music...} - #@}) +#(define-music-function + (parser location @var{arg1} @var{arg2} @dots{}) + (@var{type1?} @var{type2?} @dots{}) + #@{ + @var{@dots{}music@dots{}} + #@}) @end example @noindent where @multitable @columnfractions .33 .66 -@item @var{vari} @tab @var{i}th variable -@item @var{vari-type?} @tab type of @var{i}th variable -@item @var{...music...} @tab normal LilyPond input, using - variables as @code{#$var1}, etc. -@end multitable - -Common variable types are described in @ref{Common argument types}. -A more complete description of variable types is found in -@rextend{Music function syntax}. The complete list of defined variable -types is found in the @var{type-p-name-alist} entry of -@file{scm/lily.scm}. - -@c TODO -- find an automatic way of documenting the type-p-name-alist +@item @code{@var{argN}} +@tab @var{n}th argument -The @code{parser} and @code{location} arguments are mandatory, -and are used in some advanced situations as described in -@rextend{Music function syntax}. For substitution functions, just be sure -to include them. +@item @code{@var{typeN?}} +@tab a scheme @emph{type predicate} for which @code{@var{argN}} +must return @code{#t}. -@seealso +@item @code{@var{@dots{}music@dots{}}} +@tab normal LilyPond input, using @code{$} to reference arguments +(eg. @samp{$arg1}). +@end multitable -Notation Reference: -@ref{Common argument types}. -Extending LilyPond: -@rextend{Music function syntax}. +The @code{parser} and @code{location} arguments are mandatory, and +are used in some advanced situations as described in the +@q{Extending} manual (see @rextend{Music functions}). For +substitution functions, just be sure to include them. -@node Common argument types -@subsection Common argument types +The list of type predicates is also required. Some of the most +common type predicates used in music functions are: -In order to allow for error checking, the type of each argument -that is passed to a music function must be defined. Some of the -common types of variables are shown in the table below. +@example +boolean? +cheap-list? @emph{(use instead of }@q{list?}@emph{ for faster processing)} +ly:music? +markup? +number? +pair? +string? +symbol? +@end example -The following input types may be used as variables in a music -function. This list is not exhaustive; -more information about possible variable types -can be found in @rextend{Music function syntax}. +@noindent +For a list of available type predicates, see +@ref{Predefined type predicates}. User-defined type predicates +are also allowed. -@multitable @columnfractions .33 .66 -@headitem Input type @tab @var{vari-type?} notation -@item Integer @tab @code{integer?} -@item Float (decimal number) @tab @code{number?} -@item Text string @tab @code{string?} -@item Markup @tab @code{markup?} -@item Music expression @tab @code{ly:music?} -@item A Scheme pair @tab @code{pair?} -@end multitable @seealso -Extending LilyPond: -@rextend {Music function syntax}. +Notation Reference: +@ref{Predefined type predicates}. + +Extending: +@rextend{Music functions}. Installed Files: @file{lily/music-scheme.cc}, -@file{scm/c++.scm}. +@file{scm/c++.scm}, +@file{scm/lily.scm}. @node Substitution function examples @subsection Substitution function examples -This section introduces some substitution function examples. These -are not intended to be exhaustive, but rather to demonstrate some -of the possibilities of simple substitution functions. +This section introduces some substitution function examples. +These are not intended to be exhaustive, but rather to demonstrate +some of the possibilities of simple substitution functions. In the first example, a function is defined that simplifies setting the padding of a TextScript: @lilypond[quote,verbatim,ragged-right] -padText = #(define-music-function (parser location padding) (number?) - #{ - \once \override TextScript #'padding = #$padding - #}) +padText = +#(define-music-function + (parser location padding) + (number?) + #{ + \once \override TextScript #'padding = $padding + #}) \relative c''' { c4^"piu mosso" b a b @@ -3691,30 +3687,36 @@ padText = #(define-music-function (parser location padding) (number?) In addition to numbers, we can use music expressions such as notes for arguments to music functions: -@lilypond[quote,verbatim,ragged-right] -custosNote = #(define-music-function (parser location note) - (ly:music?) - #{ - \once \override Voice.NoteHead #'stencil = - #ly:text-interface::print - \once \override Voice.NoteHead #'text = - \markup \musicglyph #"custodes.mensural.u0" - \once \override Voice.Stem #'stencil = ##f - $note - #}) +@c TODO: use a better example (the music argument is redundant). -{ c' d' e' f' \custosNote g' } +@lilypond[quote,verbatim,ragged-right] +custosNote = +#(define-music-function + (parser location note) + (ly:music?) + #{ + \once \override Voice.NoteHead #'stencil = + #ly:text-interface::print + \once \override Voice.NoteHead #'text = + \markup \musicglyph #"custodes.mensural.u0" + \once \override Voice.Stem #'stencil = ##f + $note + #}) + +\relative c' { c4 d e f \custosNote g } @end lilypond Substitution functions with multiple arguments can be defined: @lilypond[quote,verbatim,ragged-right] -tempoPadded = #(define-music-function (parser location padding tempotext) - (number? string?) -#{ - \once \override Score.MetronomeMark #'padding = $padding - \tempo \markup { \bold $tempotext } -#}) +tempoPadded = +#(define-music-function + (parser location padding tempotext) + (number? string?) + #{ + \once \override Score.MetronomeMark #'padding = $padding + \tempo \markup { \bold $tempotext } + #}) \relative c'' { \tempo \markup { "Low tempo" } @@ -3726,3 +3728,4 @@ tempoPadded = #(define-music-function (parser location padding tempotext) @seealso +TODO: add missing @@ref's here. diff --git a/Documentation/notation/notation-appendices.itely b/Documentation/notation/notation-appendices.itely index b18810e872..6b58d17b65 100644 --- a/Documentation/notation/notation-appendices.itely +++ b/Documentation/notation/notation-appendices.itely @@ -47,6 +47,7 @@ and just before * All context properties:: * Layout properties:: * Available music functions:: +* Predefined type predicates:: * Scheme functions:: @end menu @@ -1343,6 +1344,12 @@ Internals Reference: @include identifiers.tely +@node Predefined type predicates +@appendixsec Predefined type predicates + +@include type-predicates.tely + + @node Scheme functions @appendixsec Scheme functions diff --git a/scm/c++.scm b/scm/c++.scm index 362e358b34..bc518030ae 100644 --- a/scm/c++.scm +++ b/scm/c++.scm @@ -74,4 +74,8 @@ (type-name (match-predicate obj type-p-name-alist))) (define-public (type-name predicate) - (assoc-get predicate type-p-name-alist "unknown")) + (let ((entry (assoc predicate type-p-name-alist))) + (if (pair? entry) (cdr entry) + (string-trim-right + (symbol->string (procedure-name predicate)) + #\?)))) diff --git a/scm/document-type-predicates.scm b/scm/document-type-predicates.scm new file mode 100644 index 0000000000..aff4034553 --- /dev/null +++ b/scm/document-type-predicates.scm @@ -0,0 +1,69 @@ +;;;; This file is part of LilyPond, the GNU music typesetter. +;;;; +;;;; Copyright (C) 2010 Mark Polesky <markpolesky@yahoo.com> +;;;; +;;;; LilyPond is free software: you can redistribute it and/or modify +;;;; it under the terms of the GNU General Public License as published by +;;;; the Free Software Foundation, either version 3 of the License, or +;;;; (at your option) any later version. +;;;; +;;;; LilyPond is distributed in the hope that it will be useful, +;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;;; GNU General Public License for more details. +;;;; +;;;; You should have received a copy of the GNU General Public License +;;;; along with LilyPond. If not, see <http://www.gnu.org/licenses/>. + +(define (document-type-predicate entry) + (let ((pred (procedure-name (car entry)))) + (string-append + "@item @code{" + (case pred + ;; don't print "cheap-markup?" + ((cheap-markup?) "markup?") + (else (symbol->string pred))) + "} @tab \n" + (case pred + ;; clarify `list?' vs. `cheap-list?' + ((list?) "list @emph{(use} @code{cheap-list?} + @emph{for faster processing)}") + ((cheap-list?) "list @emph{(use this instead of} + @code{list?} @emph{for faster processing)}") + (else (cdr entry))) + "\n"))) + +(define (document-type-predicate-category alist nodename) + (string-append + "@node " nodename "\n" + "@unnumberedsubsec " nodename "\n" + "\n" + "@multitable @columnfractions .33 .66\n" + "@headitem Type predicate @tab Description\n" + (apply string-append + (sort (map document-type-predicate alist) + ly:string-ci<?)) + "@end multitable\n" + "\n")) + +(define-public type-predicates-doc-string + (string-append + "@menu\n" + "* R5RS primary predicates::\n" + "* R5RS secondary predicates::\n" + "* Guile predicates::\n" + "* LilyPond scheme predicates::\n" + "* LilyPond exported predicates::\n" + "@end menu\n" + "\n" + (apply + string-append + (map + (lambda (alist-nodename-list) + (apply document-type-predicate-category + alist-nodename-list)) + `((,r5rs-primary-predicates "R5RS primary predicates") + (,r5rs-secondary-predicates "R5RS secondary predicates") + (,guile-predicates "Guile predicates") + (,lilypond-scheme-predicates "LilyPond scheme predicates") + (,lilypond-exported-predicates "LilyPond exported predicates")))))) diff --git a/scm/documentation-generate.scm b/scm/documentation-generate.scm index c64fb3a166..0e6cfe32be 100644 --- a/scm/documentation-generate.scm +++ b/scm/documentation-generate.scm @@ -32,6 +32,7 @@ "document-functions.scm" "document-translation.scm" "document-music.scm" + "document-type-predicates.scm" "document-identifiers.scm" "document-backend.scm" "document-markup.scm")) @@ -42,7 +43,7 @@ (slot-ref (all-scheme-functions-doc) 'text) (open-output-file "scheme-functions.tely")) -;;(display +;;(display ;; (markup-doc-string) ;; (open-output-file "markup-commands.tely")) @@ -54,7 +55,11 @@ (lambda (port) (dump-node (markup-list-doc-node) port 2))) -(display +(display + type-predicates-doc-string + (open-output-file "type-predicates.tely")) + +(display (identifiers-doc-string) (open-output-file "identifiers.tely")) diff --git a/scm/lily.scm b/scm/lily.scm index 8cfebbd0db..2b6ca651b4 100644 --- a/scm/lily.scm +++ b/scm/lily.scm @@ -49,8 +49,8 @@ "Render at higher resolution (using given factor) and scale down result to prevent jaggies in PNG images.") - (aux-files #t -"Create .tex, .texi, .count files in the + (aux-files #t +"Create .tex, .texi, .count files in the EPS backend.") (backend ps "Select backend. Possible values: 'eps, 'null, @@ -410,50 +410,119 @@ LilyPond safe mode. The syntax is the same as `define*-public'." (for-each ly:load init-scheme-files) +(define-public r5rs-primary-predicates + `((,boolean? . "boolean") + (,char? . "character") + (,number? . "number") + (,pair? . "pair") + (,port? . "port") + (,procedure? . "procedure") + (,string? . "string") + (,symbol? . "symbol") + (,vector? . "vector"))) + +(define-public r5rs-secondary-predicates + `((,char-alphabetic? . "alphabetic character") + (,char-lower-case? . "lower-case character") + (,char-numeric? . "numeric character") + (,char-upper-case? . "upper-case character") + (,char-whitespace? . "whitespace character") + + (,complex? . "complex number") + (,even? . "even number") + (,exact? . "exact number") + (,inexact? . "inexact number") + (,integer? . "integer") + (,negative? . "negative number") + (,odd? . "odd number") + (,positive? . "positive number") + (,rational? . "rational number") + (,real? . "real number") + (,zero? . "zero") + + (,list? . "list") + (,null? . "null") + + (,input-port? . "input port") + (,output-port? . "output port") + + ;; would this ever be used? + (,eof-object? . "end-of-file object") + )) + +(define-public guile-predicates + `((,hash-table? . "hash table") + )) + +(define-public lilypond-scheme-predicates + `((,boolean-or-symbol? . "boolean or symbol") + (,color? . "color") + (,cheap-list? . "list") + (,grob-list? . "list of grobs") + ;; this is built on cheap-list + (,list-or-symbol? . "list or symbol") + (,markup? . "markup") + (,markup-command-list? . "markup command list") + (,markup-list? . "markup list") + (,moment-pair? . "pair of moment objects") + (,number-or-grob? . "number or grob") + (,number-or-string? . "number or string") + (,number-pair? . "pair of numbers") + (,rhythmic-location? . "rhythmic location") + (,scheme? . "any type") + (,string-or-pair? . "string or pair") + (,string-or-symbol? . "string or symbol") + )) + +(define-public lilypond-exported-predicates + `((,ly:box? . "box") + (,ly:context? . "context") + (,ly:dimension? . "dimension, in staff space") + (,ly:dir? . "direction") + (,ly:dispatcher? . "dispatcher") + (,ly:duration? . "duration") + (,ly:font-metric? . "font metric") + (,ly:grob? . "graphical (layout) object") + (,ly:grob-array? . "array of grobs") + (,ly:input-location? . "input location") + (,ly:item? . "item") + (,ly:iterator? . "iterator") + (,ly:lily-lexer? . "lily-lexer") + (,ly:lily-parser? . "lily-parser") + (,ly:listener? . "listener") + (,ly:moment? . "moment") + (,ly:music? . "music") + (,ly:music-function? . "music function") + (,ly:music-list? . "list of music objects") + (,ly:music-output? . "music output") + (,ly:otf-font? . "OpenType font") + (,ly:output-def? . "output definition") + (,ly:page-marker? . "page marker") + (,ly:pango-font? . "pango font") + (,ly:paper-book? . "paper book") + (,ly:paper-system? . "paper-system Prob") + (,ly:pitch? . "pitch") + (,ly:prob? . "property object") + (,ly:score? . "score") + (,ly:simple-closure? . "simple closure") + (,ly:skyline? . "skyline") + (,ly:skyline-pair? . "pair of skylines") + (,ly:source-file? . "source file") + (,ly:spanner? . "spanner") + (,ly:stencil? . "stencil") + (,ly:stream-event? . "stream event") + (,ly:translator? . "translator") + (,ly:translator-group? . "translator group") + )) + + (set! type-p-name-alist - `((,boolean? . "boolean") - (,boolean-or-symbol? . "boolean or symbol") - (,char? . "char") - (,grob-list? . "list of grobs") - (,hash-table? . "hash table") - (,input-port? . "input port") - (,integer? . "integer") - (,list? . "list") - (,list-or-symbol? . "list or symbol") - (,ly:context? . "context") - (,ly:dimension? . "dimension, in staff space") - (,ly:dir? . "direction") - (,ly:duration? . "duration") - (,ly:font-metric? . "font metric") - (,ly:grob? . "layout object") - (,ly:grob-array? . "array of grobs") - (,ly:input-location? . "input location") - (,ly:moment? . "moment") - (,ly:music? . "music") - (,ly:music-list? . "list of music objects") - (,ly:music-output? . "music output") - (,ly:pitch? . "pitch") - (,ly:translator? . "translator") - (,ly:score? . "score") - (,ly:simple-closure? . "simple closure") - (,ly:skyline-pair? . "pair of skylines") - (,ly:stencil? . "stencil") - (,markup-list? . "list of markups") - (,markup? . "markup") - (,number-or-grob? . "number or grob") - (,number-or-string? . "number or string") - (,number-pair? . "pair of numbers") - (,number? . "number") - (,output-port? . "output port") - (,pair? . "pair") - (,procedure? . "procedure") - (,real? . "real number") - (,rhythmic-location? . "rhythmic location") - (,scheme? . "any type") - (,string? . "string") - (,string-or-pair? . "string or pair") - (,symbol? . "symbol") - (,vector? . "vector"))) + (append r5rs-primary-predicates + r5rs-secondary-predicates + guile-predicates + lilypond-scheme-predicates + lilypond-exported-predicates)) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; timing diff --git a/scm/output-lib.scm b/scm/output-lib.scm index 04accee665..8e4697dd66 100644 --- a/scm/output-lib.scm +++ b/scm/output-lib.scm @@ -329,7 +329,12 @@ and duration-log @var{log}." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Color -(define-public color? list?) +(define-public (color? x) + (and (list? x) + (= 3 (length x)) + (apply eq? #t (map number? x)) + (apply eq? #t (map (lambda (y) (<= 0 y 1)) x)))) + (define-public (rgb-color r g b) (list r g b)) ; predefined colors