Hi all, triggered by a new analysis.highlighters module that Klaus Blum shared with me last week I had a few feature/functionality wishes that I implemented, especially a kind of stylesheet support and selective activation of elements. I quickly realized that this should be generalized and factored out, and today I've implemented a new tool for the oll-core package (i.e. available for any documents using openLilyLib): properties.
Properties are related to OLL's existing option handling, but probably superior in every aspect, so I might one day deprecate the whole options feature (although that might be hard on existing code, so I'm not sure about that yet). The main features of the new properties are: * properties are type-checked * grouping in property sets may allow better organization and encapsulation * nice support for cascading behaviour * support for selective activation If you are interested you can check out the "properties" branch in the oll-core repo and play around with the attached file (also available in the usage-examples folder in oll-core). A "property set" is a group of properties with names, type check predicates, and values. When defining a property set, "design time defaults" are specified, which can be retrieved or changed at any point throughout a document. A property set might group openLilyLib package options, project options, or the available properties for a music/scheme/void-function. A macro "with-propset" allows the definition of functions that rely on a property set, that is: * When called without options the properties of the propset are available with their current values * It is possible to define "presets", which are (type-checked) subsets of a property set. When used its values override the current property values. * When called with a \with {} block individual properties can be overridden, whether from the original properties or from a preset * Presets can have parents (I have not transferred the implementation to that new code base, but I had it in place in the original code). This allows cascading stylesheets, for example a default preset specifying a line thickness for a given function, and several child presets with different colors. * Also not transferred yet is support for a logic to use/ignore items based on presets. This makes it possible to easily control which items are shown or not, for example when doing presentations or teaching. As a first step I'll make use of this in the Frames, Arrows and Highlighters modules of anaLYsis. Second I will use it in new anaLYsis modules which I have wanted to realize for a very long time: support for harmonic analysis symbols in analysis.harmony.functional, analysis.harmony.roman, and analysis.harmony.scale-degrees. This is both sort-of an announcement and a request for comments before I start building heavily on the new code base. Best Urs
\version "2.20.0" % Use oll-core from the 'properties' branch \include "oll-core/package.ily" % Define a property set % Properties hold a name, a type predicate and a default value. % The default value (as well as later assignments) are type-checked % against the predicate \definePropset demo.props #`((text ,string? "bar") (color ,color? ,red) (index ,integer? 4) ;(use-case ,symbol? "fail") ; fails on typecheck ) % Retrieve the property \markup \getProperty demo.props text % Set a property, this will be the new "current" value of the property \setProperty demo.props text "baz" \markup \getProperty demo.props text % Set a property with wrong type -> no change, will be skipped %\setProperty demo.props text #green \markup \getProperty demo.props text % Define a named preset (for a specific propset). % When used the included overrides will take precedence % over the current property values. % (type checking is active too \definePreset \with { text = boo color = #blue % index = invalid % fails type-check } demo.props my-preset % Define a function with the propset % - Due to the optional \with block at least one mandatory % argument is required. % - Within the function all properties are accessible % through the local (property '<prop-name>) function % - If validation is necessary the effective properties % (after merging) can be accessed through the % props variable testFunc = #(with-propset define-scheme-function (dummy)(boolean?) `(demo props) (markup #:with-color (property 'color) (format "~a. ~a" (property 'index) (property 'text)))) % Invoke function with currently active properties \testFunc ##t % Invoke function with a preset \testFunc \with { preset = my-preset } ##t % Invoke function with a preset plus individual override \testFunc \with { preset = my-preset index = 5 color = #magenta } ##t