API-NAME-01: tp-search-forward / tp-search-backward are marked
obsolete since 0.3.0 with tp-forward / tp-backward as the recorded
replacements, and their docstrings now document all four arguments,
the primitive's nil-PREDICATE not-`equal' default, and the raw-use
advice (call the Emacs primitives directly - the wrappers add
nothing). The wrappers keep their exact primitive-delegating bodies
so every existing call stays bit-identical; a defalias onto
tp-forward/tp-backward would have flipped both the argument order
(OBJECT/N vs PREDICATE/NOT-CURRENT) and the default matching
semantics, and would have recursed through tp-forward's own calls.
Internal callers (tp-forward, tp--forward-do) now call the
primitives, leaving the deprecated names with zero in-tree callers.
The tp-forward-do / tp-backward-do summaries now read "search TIMES
times; apply FUNCTION at the Nth match" and explicitly name
tp-search-map as the for-each, so the -do suffix stops reading as
one. tp-forward's docstring states the string-path contract
precisely (list of the FIRST N matches from position 0, point never
involved) next to the buffer path's point motion.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SRC-1: tp--pattern-apply-single now swaps START > END bounds before
branching on the object type, so the string path stops signaling a
raw substring args-out-of-range while the buffer path keeps its
historical narrow-to-region swap; the behavior is now uniform and
documented in all six tp-match-*/tp-regexp-* docstrings.
SRC-2: a SUBEXP larger than the pattern's capture-group count (per
regexp-opt-depth) signals "Regexp X has no group N" instead of
silently matching nothing, while legal non-participating and
zero-width groups keep working quietly.
Also corrects the return wording of tp-match-set/tp-regexp-set (a
NEW string for string objects, not "the modified string") and adds
the missing return sections to tp-match-add/tp-regexp-add, matching
the verified tp-match-reset behavior.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The 0.3.0 buffer registry made reactive updates walk only registered
buffers, but only tp-set/tp-reset/tp-add registered. Layer stack
mutators (tp-push-layer, tp-put-layer, hide/show, move/raise/rotate,
merge/flatten, add-to-layers) and the pattern-apply paths
(tp-match-add/-reset, tp-regexp-add/-reset) stamped tp-name via
direct set-text-properties without registering, so the moment a layer
was known from one tp-set anywhere, every buffer reached only through
those paths was silently and permanently skipped by reactive updates
- including the README's own flagship tp-push-layer example. This
regressed 0.2.0, whose full buffer-list scan reached every buffer.
Fix: every buffer write that stamps tp-name now registers the buffer
via tp-reactive--register-layer-buffer (called directly, so tp-stack
and tp-search gain no tp-ops edge):
- tp-stack.el: new tp--stack-register-layers registers every named
plist of the freshly written stack - buried and hidden layers
included, which the stack-aware GC liveness fix builds on - beside
all eleven set-text-properties sites; requires tp-reactive.
- tp-search.el: tp--deep-merge-apply and tp--reset-apply register the
target buffer for the applied props' tp-name (and any group
tp-layers entries); requires tp-reactive.
Regression tests: reactive updates reach a second buffer whose layer
arrived via tp-push-layer / tp-regexp-add / tp-match-reset after a
tp-set registered the layer elsewhere, and stack writes register
buried and hidden layers that arrived via string insertion.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reactive performance (tp-reactive/tp-render/tp-ops): layer->buffer
registry replaces full buffer-list scans on reactive updates, with a
conservative unknown->learning-scan fallback, kill-buffer pruning,
and tp-reactive-track-buffer to close the propertized-string-insert
gap; minimal-diff tp-text replacement preserves point and markers and
makes identical-text updates true no-ops; tp-gc-anonymous-layers
collects interned anonymous layers no registered buffer still shows.
Stack capabilities (tp-stack): tp-hide-layer/tp-show-layer visibility
(hidden layers stay in the stack but do not render; hiding the top
reveals the next visible layer), tp-lower-layer, tp-rotate-layer
DIRECTION/COUNT, tp-layer-stack-at, and modified-run-count returns
with NOERROR options.
Search and layer APIs (tp-search/tp-layer): SUBEXP capture groups and
START/END bounds for tp-regexp-*/tp-match-*, PREDICATE/NOT-CURRENT
exposure on tp-forward/tp-backward/-do (defaults keep 0.2.0 semantics),
multi-argument parameterized layers (define-tp/define-tps arglists of
any arity, tp-layer-props-with-args, tp-layer-arglist), and the
interactive tp-describe-layer.
79 new regression tests; combined suite 522/522 green, shuffled run
green, doctests 63/63, byte-compile clean with warnings-as-errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tp-forward-do/tp-backward-do target the TIMES-th match specifically;
when fewer matches exist the string paths applied FUNCTION to the last
available match -- the wrong target -- while buffer paths applied
nothing. Both now apply nothing on shortfall and return the available
count. Updates the two legacy with-range tests that codified the
string behavior, adds four shortfall/exact-count regression tests, and
documents the contract in both READMEs and the docstrings. Suite
443/443 green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tp--replace-match-text's string branch silently truncated longer
replacements and left residue on shorter ones ("<foo>" into a 3-char
match yielded "<fo"). Strings cannot change length in place, so the
honest contract is: same-length replacements mutate in place as before;
a different-length replacement signals a clear error directing the
caller to a buffer OBJECT. Buffer paths (delete+insert) are unchanged.
Updates the five tests that codified truncation/residue and adds a
same-length regression test; suite 439/439 green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
35 fixes across tp-layer.el, tp-stack.el, tp-search.el, tp-reactive.el
and tp-render.el, each empirically reproduced before and after:
layer-definition resolution/cycles/copying/cleanup, clipped region-local
stack mutators, symmetric backward search matching, length-changing
replacements, and reactive re-render correctness (replace-not-accumulate,
buffer-local isolation, batching union, per-interval props).
Adds four per-module regression suites (100 new tests); combined suite
is 438/438 green. tp-test-backward updated to the now-symmetric backward
matching contract it previously codified inverted. The string-vs-buffer
shortfall divergence in tp-forward-do/tp-backward-do is documented in
CHANGELOG as a known divergence rather than changed. Adds CHANGELOG.md.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tp.el (4866 lines) is now an umbrella over nine modules with an
enforceable dependency order: tp-core -> tp-reactive -> tp-layer ->
tp-ops -> tp-search -> tp-render -> tp-stack -> tp-palette ->
tp-builtins. Upward dependencies are inverted through four hook
variables installed by tp-render.el.
Also: require text-property-search (fixes tp-backward void-function),
clip tp-intervals to the requested range, add the shared clipping
interval walker tp--map-intervals and tp-face-properties, remove
synced-conflict junk files, byte-compilation now succeeds (define-tp
macroexpansion previously failed at compile time).
All 280 legacy tests pass plus 8 new tp-core tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>