+(define (doc-markup-function-properties func)
+ (let ((properties (markup-function-properties func))
+ (prop-strings (list)))
+ (for-each (lambda (prop-spec)
+ (set! prop-strings
+ (if (list? prop-spec)
+ ;; either (prop value) or (prop)
+ (cons (if (null? (cdr prop-spec))
+ (format #f "@item @code{~a}\n" (car prop-spec))
+ (format #f "@item @code{~a} (~a)\n"
+ (car prop-spec)
+ (let ((default (cadr prop-spec)))
+ (if (and (list? default)
+ (null? default))
+ "'()"
+ default))))
+ prop-strings)
+ ;; a markup command: get its properties
+ ;; FIXME: avoid cyclical references
+ (append (doc-markup-function-properties prop-spec)
+ prop-strings))))
+ (or properties (list)))
+ prop-strings))
+
+(define (doc-markup-function func-pair)
+ (let* ((f-name (symbol->string (car func-pair)))
+ (func (cdr func-pair))
+ (full-doc (procedure-documentation func))
+ (match-args (and full-doc (string-match "^\\([^)]*\\)\n" full-doc)))
+ (arg-names (if match-args
+ (with-input-from-string (match:string match-args) read)
+ (circular-list "arg")))
+ (doc-str (if match-args (match:suffix match-args) full-doc))
+ (c-name (regexp-substitute/global #f "-markup(-list)?$" f-name 'pre "" 'post))
+ (sig (markup-command-signature func))
+ (sig-type-names (map type-name sig))
+ (signature-str
+ (string-join
+ (map (lambda (x y)
+ (format #f "@var{~a} (~a)" x y))
+ arg-names sig-type-names)
+ " " )))
+
+ (string-append
+ "\n\n@item @code{\\" c-name "} " signature-str
+ "\n@funindex \\" c-name "\n"
+ "\n@cindex \\" c-name "\n"
+ (if (string? doc-str)
+ doc-str
+ "")
+ (let ((prop-strings (doc-markup-function-properties func)))
+ (if (null? prop-strings)
+ "\n"
+ (string-append "\n\n\nUsed properties:\n@itemize\n"
+ (string-concatenate prop-strings)
+ "@end itemize\n"))))))
+
+(define (markup-name<? a b)
+ (ly:string-ci<? (symbol->string (car a)) (symbol->string (car b))))
+
+(define all-markup-commands '())
+(define all-markup-list-commands '())
+
+(for-each
+ (lambda (m)
+ (module-for-each (lambda (sym var)
+ (let ((val (variable-ref var)))
+ (cond ((markup-function? val)
+ (set! all-markup-commands
+ (acons sym val all-markup-commands)))
+ ((markup-list-function? val)
+ (set! all-markup-list-commands
+ (acons sym val all-markup-list-commands))))))
+ (module-public-interface m)))
+ (cons (current-module) (map resolve-module '((lily) (scm accreg)))))
+
+(set! all-markup-commands (sort! all-markup-commands markup-name<?))
+(set! all-markup-list-commands (sort! all-markup-list-commands markup-name<?))
+
+(define (markup-category-doc-node category)
+ (let* ((category-string (symbol->string category))
+ (category-name (string-capitalize
+ (regexp-substitute/global
+ #f "-" category-string 'pre " " 'post)))
+ (markup-functions (filter
+ (lambda (fun)
+ (let ((cats (markup-function-category (cdr fun))))
+ (if (pair? cats)
+ (memq category cats)
+ (eq? category cats))))
+ all-markup-commands)))
+
+ (make <texi-node>
+ #:appendix #t
+ #:name category-name
+ #:desc ""
+ #:text (string-append
+ "@table @asis"
+ (string-concatenate
+ (map doc-markup-function markup-functions))
+ "\n@end table"))))