[Kieren]
The page in the Internals Reference doesn't
list all the properties that the grob would
support, only those for which it has a specific
default. You have to explore the interfaces to
find other interesting properties that you can
tweak. In this case, click "Item" ("This object
is of class Item"). You'll find extra-spacing-width
in the item-interface.
This is something I’ve asked a couple times before, but been dismissed… Maybe
you can help?
Is there an Automagic™ way to print out a “complete tree” of all properties
that a grob supports, including any default values?
Sure. How about the attached?
Bear in mind that this may stop working in future
versions (in fact I have a branch somewhere that
would definitely break it if I ever manage to
complete the work).
[Paolo]
Thanks.
However, when looking for a property or function that might fit what I
need, I always check for inherited stuff. In this case, unfortunately,
the search is a bit cumbersome and tricky and it's not the first time,
especially when the properties are so many and I have to write the
code quickly, that I don't find the right property.
Suppose that an object has many settable properties: there is a main
page of this object, let's call it "A", and other pages with inherited
properties (B, C, D, E etc.)
When I do a search, I first look inside A: if I don't find anything
useful, I look in B and if I don't find anything useful here too, I go
back to A and then I go to C etc.
You can understand that, when there are so many properties, jumping
back and forth from page to page is inconvenient to remember what is
available as a sum of things. In many automatic documentation of other
libraries I use, the inherited properties and functions are listed
grouped (with relative links), sometimes in small format, at the
bottom of the page to avoid this inconvenience.
It is true that the resulting page is longer, but it is not heavier to
read. Furthermore, in this way you can read only the names, without
the descriptions, of these properties and this allows you to decide
whether or not to jump to the page that defines the inherited property
to try. Mine is a suggestion, and I think it's useful to add it to the
documentation (or at least explain how to create this "extra"
documentation automatically)
Would the attached mock a good way to format
this documentation in your opinion?
Best,
Jean
\version "2.23.4"
#(define (indent n lines)
(let ((padding (make-string n #\space)))
(string-join
(map
(lambda (line)
(string-append padding line))
lines)
"\n")))
#(define (wrap n str)
(let ((components (filter
(lambda (s)
(not (string-null? s)))
(apply append
(map (lambda (s)
(string-split s #\space))
(string-split str #\newline))))))
(let loop ((rest components)
(lines-acc '())
(current-line-acc '())
(pos 0))
(if (null? rest)
(map (lambda (line)
(string-join line " "))
(reverse! (cons (reverse! current-line-acc)
lines-acc)))
(let* ((next (car rest))
(remaining (cdr rest))
(added-len (1+ (string-length next)))
(new-pos (+ pos added-len)))
(if (>= new-pos n)
(loop remaining
(cons (reverse! current-line-acc)
lines-acc)
(list next)
added-len)
(loop remaining
lines-acc
(cons next current-line-acc)
new-pos)))))))
#(define (format-symbol-list lst)
(string-join (map symbol->string lst)
", "))
#(define (format-default default)
(cond
((unspecified? default)
"")
((procedure? default)
(format #f " ~a\n" (procedure-name default)))
(else
(indent 2 (string-split (format #f "~y" default)
#\newline)))))
#(define (format-property-entry property default interfaces)
(format #f
"\
* ~a (from ~a)
~a
~a
~a"
property
(format-symbol-list interfaces)
(make-string (string-length (symbol->string property))
#\-)
(format-default default)
(indent 5 (wrap 74 (object-property property 'backend-doc)))))
#(define (basic-doc name classes interfaces)
(format #f
"
~a
~a
~a
Classes: ~a
"
name
(make-string (string-length (symbol->string name))
#\=)
(let* ((formatted-list (format-symbol-list interfaces))
(formatted-text (format #f "Interfaces supported: ~a" formatted-list)))
(string-join (wrap 79 formatted-text)
"\n"))
(format-symbol-list classes)))
info =
#(define-void-function (grob-name) (symbol?)
(let* ((definition (assq-ref all-grob-descriptions grob-name))
(meta (assq-ref definition 'meta))
(properties (alist->hash-table (assq-remove! definition 'meta)))
(classes (assq-ref meta 'classes))
(interfaces (assq-ref meta 'interfaces))
(basic (basic-doc grob-name classes interfaces))
(property-interfaces-table (make-hash-table))
(all-interfaces (ly:all-grob-interfaces)))
(for-each
(lambda (interface)
(let ((interface-properties (third (hashq-ref all-interfaces interface))))
(for-each
(lambda (property)
(if (not (object-property property 'backend-internal))
(hashq-set! property-interfaces-table
property
(cons interface
(hashq-ref property-interfaces-table property '())))))
interface-properties)))
interfaces)
(let* ((property-alist (hash-map->list cons property-interfaces-table))
(sorted-property-alist
(sort property-alist
(comparator-from-key (lambda (pair)
(symbol->string (car pair)))
string-ci<?)))
(property-descriptions
(map
(lambda (entry)
(let* ((property (car entry))
(interfaces (cdr entry))
(default-handle (hashq-get-handle properties property))
(default (if default-handle
(cdr default-handle)
*unspecified*)))
(format-property-entry property default interfaces)))
sorted-property-alist)))
(display (string-append basic
(string-join property-descriptions "\n\n")
"\n")
(current-error-port)))))
\info BarLine