58.10 Formula Source Selection and Matching
Source queries address retained TeX character ranges, named matches address formula parts, and glyph matching addresses rendered outlines. None of these APIs proves algebraic equivalence. Use selectors for lookup, a plan for inspection, and a transition request for animation; the sections below keep those roles separate.
See also Formula Construction and Layout, Formula Assemblies and Named Parts.
58.10.1 Source-Addressable Formulas
Source selectors address character ranges in the canonical TeX source retained by math-tex. They complement named formula fragments; they do not recognize algebraic roles or prove mathematical equivalence. Source indices are Racket string-character indices in half-open ranges, so (source-span 2 5) selects characters 2 through 4.
struct
(struct source-span (start end))
start : exact-nonnegative-integer? end : exact-nonnegative-integer?
struct
(struct source-occurrence (selector index))
selector : source-selector? index : exact-nonnegative-integer?
struct
(struct source-part (name selector))
name : symbol? selector : source-selector?
procedure
(source-selector? value) → boolean?
value : any/c
Selector descriptions are model data; they do not typeset a formula.
> (source-selector? (source-span 2 5)) #t
> (source-selector? (source-occurrence "x" 1)) #t
procedure
(formula-source-match? value) → boolean?
value : any/c
struct
(struct visual-selection (root paths) #:transparent) root : visual-path? paths : (listof list?)
58.10.1.1 Querying Retained Source
procedure
(formula-source formula) → string?
formula : formula-assembly-visual?
procedure
(formula-find formula selector) → (listof formula-source-match?)
formula : formula-assembly-visual? selector : source-selector?
procedure
(formula-source-select formula selector) → visual-selection?
formula : formula-assembly-visual? selector : source-selector?
procedure
(formula-source-select-one formula selector) → visual-selection? formula : formula-assembly-visual? selector : source-selector?
58.10.1.2 Planning String Correspondences
procedure
(plan-matching-strings source destination [ #:matches matches #:copies copies]) → string-match-plan? source : formula-assembly-visual? destination : formula-assembly-visual? matches : (listof string-match?) = '() copies : (listof formula-string-copy?) = '()
procedure
(string-match source destination [ #:route route #:mode mode #:appearance-complete-at-x appearance-complete-at-x #:appearance-duration appearance-duration]) → string-match? source : source-selector? destination : source-selector? route : (or/c #f formula-route?) = #f mode : (or/c 'auto 'rigid 'glyphwise 'cross-fade) = 'auto appearance-complete-at-x : (or/c #f source-selector?) = #f
appearance-duration : (or/c #f (and/c finite-real? positive? (<=/c 1))) = #f
When both appearance keywords are supplied, the part keeps its ordinary route, but its changed appearance completes when that route first reaches the current x-coordinate of appearance-complete-at-x. The duration is a fraction of the enclosing transition: the old and new appearances cross-fade only in the interval immediately preceding that deadline. This is useful for a moving + that should become - exactly as it passes an equality sign.
procedure
(formula-string-copy source destination [ #:route route #:mode mode]) → formula-string-copy? source : source-selector? destination : source-selector? route : (or/c #f formula-route?) = #f mode : (or/c 'auto 'rigid 'glyphwise 'cross-fade) = 'auto
procedure
(string-match? value) → boolean?
value : any/c
procedure
(formula-string-copy? value) → boolean?
value : any/c
procedure
(string-match-plan? value) → boolean?
value : any/c
procedure
(string-match-plan->datum plan) → immutable-hash?
plan : string-match-plan?
procedure
(transform-matching-strings source destination [ #:matches matches #:key-map key-map #:protect-source protect-source #:protect-destination protect-destination #:copies copies #:on-ambiguity on-ambiguity #:path-arc path-arc #:mismatch-mode mismatch-mode]) → transform-formula-parts-request? source : formula-assembly-visual? destination : formula-assembly-visual? matches : (listof string-match?) = '() key-map : (listof string-match?) = '() protect-source : (listof source-selector?) = '() protect-destination : (listof source-selector?) = '() copies : (listof formula-string-copy?) = '() on-ambiguity : (or/c 'left-to-right 'error) = 'left-to-right path-arc : finite-real? = 0 mismatch-mode : (or/c 'fade 'fade-transform) = 'fade
58.10.1.3 Part Routes and Copies
procedure
(formula-part-path source-name destination-name route) → formula-part-path? source-name : symbol? destination-name : symbol? route : formula-route?
procedure
(formula-part-copy source-name destination-name route) → formula-part-copy? source-name : symbol? destination-name : symbol? route : formula-route?
procedure
(formula-part-path? value) → boolean?
value : any/c
procedure
(formula-part-copy? value) → boolean?
value : any/c
procedure
(formula-route? value) → boolean?
value : any/c
procedure
(formula-arc #:angle angle) → formula-route?
angle : finite-real?
procedure
(formula-relative-path geometry) → formula-route?
geometry : path-geometry?
58.10.1.4 Generated SVG Fragments
procedure
(tagged-formula-fragment-visual? value) → boolean?
value : any/c
procedure
(tagged-formula-fragment-visual-svg-source visual) → string?
visual : tagged-formula-fragment-visual?
58.10.1.5 Part and Glyph Transitions
procedure
(transform-matching-parts source destination [ #:matches matches]) → transform-formula-parts-request? source : formula-assembly-visual? destination : formula-assembly-visual? matches : (listof formula-part-match?) = '()
Exact matches render as one rigid SVG group that moves with its local transform. Changed explicit matches are moving cross-fades, and unmatched fragments use the normal fade-out/fade-in behavior. This operation does not infer algebraic equivalence, parse TeX tokens, choose paths/arcs for the movement, or morph glyph outlines.
procedure
(transform-matching-glyphs source destination [ #:matches matches #:path-arc path-arc #:part-paths part-paths #:copies copies #:mismatch-mode mismatch-mode #:changed-mode changed-mode]) → transform-formula-parts-request? source : formula-assembly-visual? destination : formula-assembly-visual? matches : (listof formula-part-match?) = '() path-arc : finite-real? = 0 part-paths : (listof formula-part-path?) = '() copies : (listof formula-part-copy?) = '() mismatch-mode : (or/c 'fade 'fade-transform) = 'fade changed-mode : (or/c 'fade 'morph) = 'fade
This matches and moves whole rendered glyph leaves. 'fade is the default: changed matches use the ordinary moving cross-fade. With #:changed-mode 'morph, a changed matched pair instead interpolates its outline only when both cropped dvisvgm SVG fragments expand to one identically painted path whose positive-length contours are all closed and compatible in count. Animate globally pairs those destination contours with the source, phase-aligns them without reversing their traversal, normalizes the resulting paths to compatible cubic segments, and uses that path geometry only for interior frames; the ordinary tagged SVG fragments remain exact endpoints. Glyphs with multiple independently painted paths, open contours, incompatible contour topology, changed paint, or unsupported geometry safely fall back to the moving cross-fade.
This operation does not derive a mathematical operation, identify TeX characters or terms, perform semantic grouping, or infer which changed glyphs should be paired.
58.10.1.6 Anchored Rewrites
procedure
(rewrite-formula source destination #:anchor anchor [ #:matches matches #:stationary stationary #:path-arc path-arc #:part-paths part-paths #:copies copies #:mismatch-mode mismatch-mode]) → transform-formula-parts-request? source : formula-assembly-visual? destination : formula-assembly-visual? anchor : (or/c symbol? formula-part-match?) matches : (listof formula-part-match?) = '() stationary : (listof (or/c symbol? formula-part-match?)) = '() path-arc : finite-real? = 0 part-paths : (listof formula-part-path?) = '() copies : (listof formula-part-copy?) = '() mismatch-mode : (or/c 'fade 'fade-transform) = 'fade
When scene-play compiles the request, Animate translates the complete destination layout so the destination anchor coincides with the corresponding part in the current source formula. Consequently, a sequence of rewrites keeps the anchor fixed even when the formula values passed as earlier templates were constructed at their own default positions. The translation preserves the target formula’s TeX spacing and baselines.
Each stationary entry names an additional matched pair: a symbol means the same source and destination part name, while a formula-part-match permits different names. The pair is made explicit, and at clip compilation the destination fragment receives the current source fragment’s exact affine transform. Thus several selected terms can remain fixed even if the rest of the destination layout moves or reflows. This is an explicit presentation choice; it does not infer which terms should remain still or maintain a general layout constraint between them.
The remaining keywords have the same meaning as in transform-matching-parts: explicit matches take priority, routes and copies select intentional term motion, and 'fade-transform cross-fades remaining unmatched parts while moving them. Like the lower-level operation, this is whole-fragment correspondence rather than TeX parsing or glyph-outline morphing.
58.10.1.7 Derivation Steps
procedure
(formula-step destination [ #:anchor anchor #:stationary stationary #:matches matches #:path-arc path-arc #:part-paths part-paths #:copies copies #:mismatch-mode mismatch-mode #:duration duration #:pause pause #:explanation explanation]) → formula-derivation-step? destination : formula-assembly-visual? anchor : (or/c false/c symbol? formula-part-match?) = #f stationary : (listof (or/c symbol? formula-part-match?)) = '() matches : (listof formula-part-match?) = '() path-arc : finite-real? = 0 part-paths : (listof formula-part-path?) = '() copies : (listof formula-part-copy?) = '() mismatch-mode : (or/c 'fade 'fade-transform) = 'fade duration : (and/c finite-real? positive?) = 1 pause : (and/c finite-real? (>=/c 0)) = 1/2 explanation : (or/c false/c string?) = #f
anchor defaults to #f, which means that the derivation’s shared anchor is used. A step can override it with a same-name symbol or an explicit formula-part-match. stationary has the same meaning as in rewrite-formula and makes additional matched parts fixed for this one step. This data does not claim that the rewrite is algebraically valid; it records the author’s chosen presentation.
procedure
(formula-derivation-step? value) → boolean?
value : any/c
procedure
(formula-derivation scene initial #:anchor anchor #:steps steps [ #:explanation-position explanation-position #:explanation-id explanation-id #:explanation-font-size explanation-font-size #:explanation-color explanation-color]) → scene? scene : scene? initial : formula-assembly-visual? anchor : (or/c symbol? formula-part-match?) steps : (listof formula-derivation-step?) explanation-position : (or/c false/c vec2?) = #f explanation-id : symbol? = 'derivation-note explanation-font-size : (and/c finite-real? positive?) = 1/4 explanation-color : any/c = "darkslategray"
When any step has an explanation, supply explanation-position. The builder creates plain text with explanation-id, which must be absent from the initial scene. Later explanations replace only that generated Visual. The final explanation remains visible unless a later step omits it.
This is immutable convenience syntax over existing scene and formula APIs. It does not parse TeX, infer operations, prove a derivation, choose matches/routes, or automatically lay out the explanation.